From f078c77e32118f36476cd565b5513ac031f13f15 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sat, 25 Oct 2025 22:36:47 +0200 Subject: [PATCH 01/86] Make sure 0 groups works --- src/ram_geometry.jl | 2 +- src/solver.jl | 53 +++++-- src/wing_geometry.jl | 2 +- src/yaml_geometry.jl | 2 +- test/data/solver/wings/solver_test_wing.yaml | 12 ++ test/solver/test_solver.jl | 148 +++++++++++++++++++ test/yaml_geometry/test_wing_constructor.jl | 7 +- 7 files changed, 206 insertions(+), 20 deletions(-) diff --git a/src/ram_geometry.jl b/src/ram_geometry.jl index e352c4e2..c267d727 100644 --- a/src/ram_geometry.jl +++ b/src/ram_geometry.jl @@ -415,7 +415,7 @@ function RamAirWing( interp_steps=n_sections # TODO: check if interpolations are still needed ) - !(n_panels % n_groups == 0) && throw(ArgumentError("Number of panels should be divisible by number of groups")) + !(n_groups == 0 || n_panels % n_groups == 0) && throw(ArgumentError("Number of panels should be divisible by number of groups")) !isapprox(spanwise_direction, [0.0, 1.0, 0.0]) && throw(ArgumentError("Spanwise direction has to be [0.0, 1.0, 0.0], not $spanwise_direction")) # Load or create polars diff --git a/src/solver.jl b/src/solver.jl index ecf34e3b..8b2d75fd 100644 --- a/src/solver.jl +++ b/src/solver.jl @@ -292,21 +292,29 @@ function solve!(solver::Solver, body_aero::BodyAerodynamics, gamma_distribution= moment_coeff_dist[i] = moment_dist[i] / (q_inf * projected_area) end - group_moment_dist = solver.sol.group_moment_dist - group_moment_coeff_dist = solver.sol.group_moment_coeff_dist - group_moment_dist .= 0.0 - group_moment_coeff_dist .= 0.0 - panel_idx = 1 - group_idx = 1 - for wing in body_aero.wings - panels_per_group = wing.n_panels ÷ wing.n_groups - for _ in 1:wing.n_groups - for _ in 1:panels_per_group - group_moment_dist[group_idx] += moment_dist[panel_idx] - group_moment_coeff_dist[group_idx] += moment_coeff_dist[panel_idx] - panel_idx += 1 + # Only compute group moments if there are groups + if length(solver.sol.group_moment_dist) > 0 + group_moment_dist = solver.sol.group_moment_dist + group_moment_coeff_dist = solver.sol.group_moment_coeff_dist + group_moment_dist .= 0.0 + group_moment_coeff_dist .= 0.0 + panel_idx = 1 + group_idx = 1 + for wing in body_aero.wings + if wing.n_groups > 0 + panels_per_group = wing.n_panels ÷ wing.n_groups + for _ in 1:wing.n_groups + for _ in 1:panels_per_group + group_moment_dist[group_idx] += moment_dist[panel_idx] + group_moment_coeff_dist[group_idx] += moment_coeff_dist[panel_idx] + panel_idx += 1 + end + group_idx += 1 + end + else + # Skip panels for wings with n_groups=0 + panel_idx += wing.n_panels end - group_idx += 1 end end @@ -689,8 +697,8 @@ jac, results = linearize( ) ``` """ -function linearize(solver::Solver, body_aero::BodyAerodynamics, y::Vector{T}; - theta_idxs=1:4, +function linearize(solver::Solver, body_aero::BodyAerodynamics, y::Vector{T}; + theta_idxs=1:4, delta_idxs=nothing, va_idxs=nothing, omega_idxs=nothing, @@ -700,6 +708,19 @@ function linearize(solver::Solver, body_aero::BodyAerodynamics, y::Vector{T}; !(length(body_aero.wings) == 1) && throw(ArgumentError("Linearization only works for a body_aero with one wing")) wing = body_aero.wings[1] + # Validate that theta_idxs and delta_idxs match the number of groups + if !isnothing(theta_idxs) && wing.n_groups > 0 + length(theta_idxs) != wing.n_groups && throw(ArgumentError( + "Length of theta_idxs ($(length(theta_idxs))) must match number of groups ($(wing.n_groups))")) + end + if !isnothing(delta_idxs) && wing.n_groups > 0 + length(delta_idxs) != wing.n_groups && throw(ArgumentError( + "Length of delta_idxs ($(length(delta_idxs))) must match number of groups ($(wing.n_groups))")) + end + if wing.n_groups == 0 && (!isnothing(theta_idxs) || !isnothing(delta_idxs)) + throw(ArgumentError("Cannot use theta_idxs or delta_idxs when wing has n_groups=0 (no group functionality)")) + end + init_va = body_aero.cache[1][body_aero.va] init_va .= body_aero.va if !isnothing(theta_idxs) diff --git a/src/wing_geometry.jl b/src/wing_geometry.jl index 506b91b4..bb1f5e06 100644 --- a/src/wing_geometry.jl +++ b/src/wing_geometry.jl @@ -235,7 +235,7 @@ function Wing(n_panels::Int; spanwise_distribution::PanelDistribution=LINEAR, spanwise_direction::PosVector=MVec3([0.0, 1.0, 0.0]), remove_nan=true) - !(n_panels % n_groups == 0) && throw(ArgumentError("Number of panels should be divisible by number of groups")) + !(n_groups == 0 || n_panels % n_groups == 0) && throw(ArgumentError("Number of panels should be divisible by number of groups")) panel_props = PanelProperties{n_panels}() Wing(n_panels, n_groups, spanwise_distribution, panel_props, spanwise_direction, Section[], Section[], remove_nan) end diff --git a/src/yaml_geometry.jl b/src/yaml_geometry.jl index 1abf3118..3ba618f5 100644 --- a/src/yaml_geometry.jl +++ b/src/yaml_geometry.jl @@ -190,7 +190,7 @@ function Wing( remove_nan=true, prn=false ) - !(n_panels % n_groups == 0) && throw(ArgumentError("Number of panels should be divisible by number of groups")) + !(n_groups == 0 || n_panels % n_groups == 0) && throw(ArgumentError("Number of panels should be divisible by number of groups")) !isapprox(spanwise_direction, [0.0, 1.0, 0.0]) && throw(ArgumentError("Spanwise direction has to be [0.0, 1.0, 0.0], not $spanwise_direction")) prn && @info "Reading YAML wing configuration from $geometry_file" diff --git a/test/data/solver/wings/solver_test_wing.yaml b/test/data/solver/wings/solver_test_wing.yaml index e69de29b..14969bce 100644 --- a/test/data/solver/wings/solver_test_wing.yaml +++ b/test/data/solver/wings/solver_test_wing.yaml @@ -0,0 +1,12 @@ +wing_sections: + headers: [airfoil_id, LE_x, LE_y, LE_z, TE_x, TE_y, TE_z] + data: + - [1, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0] + - [1, 0.0, -1.0, 0.0, 1.0, -1.0, 0.0] + +wing_airfoils: + alpha_range: [-10, 10, 1] + reynolds: 1000000 + headers: [airfoil_id, type, info_dict] + data: + - [1, polars, {csv_file_path: ""}] diff --git a/test/solver/test_solver.jl b/test/solver/test_solver.jl index 1d60061a..0dbb9971 100644 --- a/test/solver/test_solver.jl +++ b/test/solver/test_solver.jl @@ -29,4 +29,152 @@ using Test rm(settings_file; force=true) end end + + @testset "Solver with n_groups=0" begin + # Test that solver works correctly when n_groups=0 (no group functionality) + settings_file = create_temp_wing_settings("solver", "solver_test_wing.yaml"; + alpha=5.0, beta=0.0, wind_speed=10.0, n_groups=0) + + try + settings = VSMSettings(settings_file) + wing = Wing(settings) + @test wing.n_groups == 0 + + body_aero = BodyAerodynamics([wing]) + solver = Solver(body_aero, settings) + + # Verify solver has zero groups + @test length(solver.sol.group_moment_dist) == 0 + @test length(solver.sol.group_moment_coeff_dist) == 0 + + # Test that solve! works without errors + va = [10.0, 0.0, 0.0] + set_va!(body_aero, va) + sol = solve!(solver, body_aero) + + @test sol isa VSMSolution + @test sol.solver_status == SUCCESS + + # Verify that group moments are empty + @test length(sol.group_moment_dist) == 0 + @test length(sol.group_moment_coeff_dist) == 0 + + # But force and moment should still be computed + @test !all(sol.force .== 0.0) + @test norm(sol.force) > 0 + + finally + rm(settings_file; force=true) + end + end + + @testset "Linearize with n_groups=0" begin + # Test that linearize works correctly when n_groups=0 + settings_file = create_temp_wing_settings("solver", "solver_test_wing.yaml"; + alpha=5.0, beta=0.0, wind_speed=10.0, n_groups=0, n_panels=4) + + try + settings = VSMSettings(settings_file) + wing = Wing(settings) + @test wing.n_groups == 0 + + body_aero = BodyAerodynamics([wing]) + solver = Solver(body_aero, settings) + + # Set velocity + va = [10.0, 0.0, 0.0] + set_va!(body_aero, va) + + # Test linearize with only velocity (no theta or delta since n_groups=0) + y = va # Only velocity in input vector + jac, results = VortexStepMethod.linearize( + solver, + body_aero, + y; + theta_idxs=nothing, + delta_idxs=nothing, + va_idxs=1:3, + omega_idxs=nothing + ) + + # Results should only have 6 elements (force + moment, no group moments) + @test length(results) == 6 + @test size(jac) == (6, 3) # 6 outputs, 3 inputs (vx, vy, vz) + + # Verify forces are non-zero + @test norm(results[1:3]) > 0 + + # Test that using theta_idxs with n_groups=0 throws an error + @test_throws ArgumentError VortexStepMethod.linearize( + solver, + body_aero, + [0.0, 10.0, 0.0, 0.0]; # Invalid: trying to use theta + theta_idxs=1:1, + va_idxs=2:4 + ) + + # Test that using delta_idxs with n_groups=0 throws an error + @test_throws ArgumentError VortexStepMethod.linearize( + solver, + body_aero, + [0.0, 10.0, 0.0, 0.0]; # Invalid: trying to use delta + delta_idxs=1:1, + va_idxs=2:4 + ) + + finally + rm(settings_file; force=true) + end + end + + @testset "Linearize theta_idxs validation" begin + # Test that theta_idxs length must match n_groups + settings_file = create_temp_wing_settings("solver", "solver_test_wing.yaml"; + alpha=5.0, beta=0.0, wind_speed=10.0, n_groups=2, n_panels=4) + + try + settings = VSMSettings(settings_file) + wing = Wing(settings) + @test wing.n_groups == 2 + + body_aero = BodyAerodynamics([wing]) + solver = Solver(body_aero, settings) + + va = [10.0, 0.0, 0.0] + set_va!(body_aero, va) + + # Test with correct number of theta angles (2) + y_correct = [0.0, 0.0, 10.0, 0.0, 0.0] # 2 theta + 3 va + jac, results = VortexStepMethod.linearize( + solver, + body_aero, + y_correct; + theta_idxs=1:2, + va_idxs=3:5 + ) + @test size(jac, 1) == 8 # 6 + 2 group moments + + # Test with wrong number of theta angles (should throw error) + y_wrong = [0.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0] # 4 theta + 3 va + @test_throws ArgumentError VortexStepMethod.linearize( + solver, + body_aero, + y_wrong; + theta_idxs=1:4, # Wrong: 4 angles but only 2 groups + va_idxs=5:7 + ) + + # Test with wrong number of delta angles + @test_throws ArgumentError VortexStepMethod.linearize( + solver, + body_aero, + y_wrong; + delta_idxs=1:4, # Wrong: 4 angles but only 2 groups + va_idxs=5:7 + ) + + finally + rm(settings_file; force=true) + end + end end diff --git a/test/yaml_geometry/test_wing_constructor.jl b/test/yaml_geometry/test_wing_constructor.jl index b7b30a45..19ec9869 100644 --- a/test/yaml_geometry/test_wing_constructor.jl +++ b/test/yaml_geometry/test_wing_constructor.jl @@ -151,7 +151,12 @@ wing_airfoils: # Test invalid n_panels/n_groups combination @test_throws ArgumentError Wing(test_yaml_path; n_panels=5, n_groups=2) - + + # Test n_groups=0 (no grouping functionality) + wing_no_groups = Wing(test_yaml_path; n_panels=4, n_groups=0) + @test wing_no_groups.n_groups == 0 + @test wing_no_groups.n_panels == 4 + # Test invalid spanwise direction @test_throws ArgumentError Wing(test_yaml_path; spanwise_direction=[1.0, 0.0, 0.0]) end From dba02d946901d56eb4e3141ab75554099d15e9e8 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sun, 26 Oct 2025 10:45:22 +0100 Subject: [PATCH 02/86] Unify Wing and RamAirWing --- docs/src/types.md | 10 +- examples/bench.jl | 6 +- examples/ram_air_kite.jl | 8 +- src/VortexStepMethod.jl | 4 +- src/body_aerodynamics.jl | 6 +- src/{ram_geometry.jl => obj_geometry.jl} | 239 ++++------------------- src/solver.jl | 8 +- src/wing_geometry.jl | 197 ++++++++++++++++++- test/body_aerodynamics/test_results.jl | 2 +- test/plotting/test_plotting.jl | 2 +- test/ram_geometry/test_kite_geometry.jl | 12 +- test/solver/test_solver.jl | 45 ++++- test/wake/test_wake.jl | 2 +- 13 files changed, 309 insertions(+), 232 deletions(-) rename src/{ram_geometry.jl => obj_geometry.jl} (66%) diff --git a/docs/src/types.md b/docs/src/types.md index 14e5cbdd..de083b35 100644 --- a/docs/src/types.md +++ b/docs/src/types.md @@ -24,17 +24,17 @@ AeroData ``` ## Wing Geometry, Panel and Aerodynamics -A body is constructed of one or more abstract wings. An abstract wing can be a Wing or a RamAirWing. -A Wing/ RamAirWing has one or more sections. +A body is constructed of one or more abstract wings. All wings are of type Wing. +A Wing has one or more sections and can be created from YAML files or OBJ geometry. ```@docs Section Section(LE_point::PosVector, TE_point::PosVector, aero_model) Wing Wing(n_panels::Int; spanwise_distribution::PanelDistribution=LINEAR, spanwise_direction::PosVector=MVec3([0.0, 1.0, 0.0])) -RamAirWing -RamAirWing(obj_path, dat_path; alpha=0.0, crease_frac=0.75, wind_vel=10., mass=1.0, - n_panels=54, n_sections=n_panels+1, spanwise_distribution=UNCHANGED, +ObjWing +ObjWing(obj_path, dat_path; alpha=0.0, crease_frac=0.75, wind_vel=10., mass=1.0, + n_panels=54, n_sections=n_panels+1, spanwise_distribution=UNCHANGED, spanwise_direction=[0.0, 1.0, 0.0]) BodyAerodynamics ``` diff --git a/examples/bench.jl b/examples/bench.jl index 89544278..90c41ff1 100644 --- a/examples/bench.jl +++ b/examples/bench.jl @@ -56,9 +56,9 @@ println("Rectangular wing, solve:") @time solve(vsm_solver, body_aero, nothing) # Create wing geometry -wing = RamAirWing( - joinpath("data", "ram_air_kite", "ram_air_kite_body.obj"), - joinpath("data", "ram_air_kite", "ram_air_kite_foil.dat"); +wing = ObjWing( + joinpath("data", "ram_air_kite", "ram_air_kite_body.obj"), + joinpath("data", "ram_air_kite", "ram_air_kite_foil.dat"); prn=false ) body_aero = BodyAerodynamics([wing]) diff --git a/examples/ram_air_kite.jl b/examples/ram_air_kite.jl index f10b8d5b..13e60c62 100644 --- a/examples/ram_air_kite.jl +++ b/examples/ram_air_kite.jl @@ -9,9 +9,9 @@ DEFORM = false LINEARIZE = false # Create wing geometry -wing = RamAirWing( - joinpath("data", "ram_air_kite", "ram_air_kite_body.obj"), - joinpath("data", "ram_air_kite", "ram_air_kite_foil.dat"); +wing = ObjWing( + joinpath("data", "ram_air_kite", "ram_air_kite_body.obj"), + joinpath("data", "ram_air_kite", "ram_air_kite_foil.dat"); prn=PRN ) body_aero = BodyAerodynamics([wing];) @@ -21,7 +21,7 @@ println("First init") if DEFORM # Linear interpolation of alpha from 10° at one tip to 0° at the other println("Deform") - @time VortexStepMethod.smooth_deform!(wing, deg2rad.([10,20,10,0]), deg2rad.([-10,0,-10,0])) + @time group_deform!(wing, deg2rad.([10,20,10,0]), deg2rad.([-10,0,-10,0]); smooth=true) println("Deform init") @time VortexStepMethod.reinit!(body_aero; init_aero=false) end diff --git a/src/VortexStepMethod.jl b/src/VortexStepMethod.jl index c852c48e..64a4a657 100644 --- a/src/VortexStepMethod.jl +++ b/src/VortexStepMethod.jl @@ -27,7 +27,7 @@ using Xfoil # Export public interface export VSMSettings, WingSettings, SolverSettings -export Wing, Section, RamAirWing, reinit! +export Wing, Section, ObjWing, reinit! export BodyAerodynamics export Solver, solve, solve_base!, solve!, VSMSolution, linearize export calculate_results @@ -272,7 +272,7 @@ end include("settings.jl") include("wing_geometry.jl") include("polars.jl") -include("ram_geometry.jl") +include("obj_geometry.jl") include("yaml_geometry.jl") include("filament.jl") include("panel.jl") diff --git a/src/body_aerodynamics.jl b/src/body_aerodynamics.jl index 87e75fec..6444a598 100644 --- a/src/body_aerodynamics.jl +++ b/src/body_aerodynamics.jl @@ -5,7 +5,7 @@ Main structure for calculating aerodynamic properties of bodies. Use the constru # Fields - panels::Vector{Panel}: Vector of [Panel](@ref) structs -- wings::Union{Vector{Wing}, Vector{RamAirWing}}: A vector of wings; a body can have multiple wings +- wings::Vector{Wing}: A vector of wings; a body can have multiple wings - `va::MVec3` = zeros(MVec3): A vector of the apparent wind speed, see: [MVec3](@ref) - `omega`::MVec3 = zeros(MVec3): A vector of the turn rates around the kite body axes - `gamma_distribution`=zeros(Float64, P): A vector of the circulation @@ -23,7 +23,7 @@ Main structure for calculating aerodynamic properties of bodies. Use the constru """ @with_kw mutable struct BodyAerodynamics{P} panels::Vector{Panel} - wings::Union{Vector{Wing}, Vector{RamAirWing}} + wings::Vector{Wing} _va::MVec3 = zeros(MVec3) omega::MVec3 = zeros(MVec3) gamma_distribution::MVector{P, Float64} = zeros(P) @@ -142,7 +142,7 @@ function reinit!(body_aero::BodyAerodynamics; # Create panels for i in 1:wing.n_panels - if wing isa RamAirWing + if !isnothing(wing.delta_dist) delta = wing.delta_dist[i] else delta = 0.0 diff --git a/src/ram_geometry.jl b/src/obj_geometry.jl similarity index 66% rename from src/ram_geometry.jl rename to src/obj_geometry.jl index c267d727..dec38cb7 100644 --- a/src/ram_geometry.jl +++ b/src/obj_geometry.jl @@ -14,7 +14,7 @@ Read vertices and faces from an OBJ file. function read_faces(filename) vertices = [] faces = [] - + open(filename) do file for line in eachline(file) if startswith(line, "v ") && !startswith(line, "vt") && !startswith(line, "vn") @@ -115,13 +115,13 @@ function create_interpolations(vertices, circle_center_z, radius, gamma_tip, R=I gamma_range = range(-gamma_tip+1e-6, gamma_tip-1e-6, interp_steps) stepsize = gamma_range.step.hi vz_centered = [v[3] - circle_center_z for v in vertices] - + te_gammas = zeros(length(gamma_range)) le_gammas = zeros(length(gamma_range)) trailing_edges = zeros(3, length(gamma_range)) leading_edges = zeros(3, length(gamma_range)) areas = zeros(length(gamma_range)) - + for (j, gamma) in enumerate(gamma_range) trailing_edges[1, j] = -Inf leading_edges[1, j] = Inf @@ -164,7 +164,7 @@ function create_interpolations(vertices, circle_center_z, radius, gamma_tip, R=I te_interp = ntuple(i -> linear_interpolation(le_gammas, trailing_edges[i, :], extrapolation_bc=Line()), 3) area_interp = linear_interpolation(gamma_range, areas, extrapolation_bc=Line()) - + return (le_interp, te_interp, area_interp) end @@ -187,26 +187,26 @@ Calculate center of mass of a mesh and translate vertices so that COM is at orig function center_to_com!(vertices, faces; prn=true) area_total = 0.0 com = zeros(3) - + for face in faces if length(face) == 3 # Triangle case v1 = vertices[face[1]] v2 = vertices[face[2]] v3 = vertices[face[3]] - + # Calculate triangle area and centroid normal = cross(v2 - v1, v3 - v1) area = norm(normal) / 2 centroid = (v1 + v2 + v3) / 3 - + area_total += area com -= area * centroid else throw(ArgumentError("Triangulate faces in a CAD program first")) end end - + com = com / area_total !(abs(com[2]) < 0.01) && throw(ArgumentError("Center of mass $com of .obj file has to lie on the xz-plane.")) prn && @info "Centering vertices of .obj file to the center of mass: $com" @@ -220,7 +220,7 @@ end """ calculate_inertia_tensor(vertices, faces, mass, com) -Calculate the inertia tensor for a triangulated surface mesh, assuming a thin shell with uniform +Calculate the inertia tensor for a triangulated surface mesh, assuming a thin shell with uniform surface density. # Arguments @@ -244,23 +244,23 @@ function calculate_inertia_tensor(vertices, faces, mass, com) # Initialize inertia tensor I = zeros(3, 3) total_area = 0.0 - + for face in faces v1 = vertices[face[1]] .- com v2 = vertices[face[2]] .- com v3 = vertices[face[3]] .- com - + # Calculate triangle area normal = cross(v2 - v1, v3 - v1) area = norm(normal) / 2 total_area += area - + # Calculate contribution to inertia tensor for i in 1:3 for j in 1:3 # Vertices relative to center of mass points = [v1, v2, v3] - + # Calculate contribution to inertia tensor for p in points if i == j @@ -274,7 +274,7 @@ function calculate_inertia_tensor(vertices, faces, mass, com) end end end - + # Scale by mass/total_area to get actual inertia tensor return (mass / total_area) * I / 3 end @@ -291,14 +291,14 @@ function calc_inertia_y_rotation(I_b_tensor) # Transform inertia tensor I_rotated = R_y * I_b_tensor * R_y' # We want the off-diagonal xz elements to be zero - F[1] = I_rotated[1,3] + F[1] = I_rotated[1,3] end - + theta0 = [0.0] prob = NonlinearProblem(eq!, theta0, nothing) sol = NonlinearSolve.solve(prob, NewtonRaphson()) theta_opt = sol.u[1] - + R_b_p = [ cos(theta_opt) 0 sin(theta_opt); 0 1 0; @@ -312,67 +312,18 @@ end """ - RamAirWing <: AbstractWing - -A ram-air wing model that represents a curved parafoil with deformable aerodynamic surfaces. - -## Core Features -- Curved wing geometry derived from 3D mesh (.obj file) -- Aerodynamic properties based on 2D airfoil data (.dat file) -- Support for control inputs (twist angles and trailing edge deflections) -- Inertial and geometric properties calculation - -## Notable Fields -- `n_panels::Int16`: Number of panels in aerodynamic mesh -- `n_groups::Int16`: Number of control groups for distributed deformation -- `mass::Float64`: Total wing mass in kg -- `gamma_tip::Float64`: Angular extent from center to wing tip -- `inertia_tensor::Matrix{Float64}`: Full 3x3 inertia tensor in the kite body frame -- `T_cad_body::MVec3`: Translation vector from CAD frame to body frame -- `R_cad_body::MMat3`: Rotation matrix from CAD frame to body frame -- `radius::Float64`: Wing curvature radius -- `theta_dist::Vector{Float64}`: Panel twist angle distribution -- `delta_dist::Vector{Float64}`: Trailing edge deflection distribution - -See constructor `RamAirWing(obj_path, dat_path; kwargs...)` for usage details. -""" -mutable struct RamAirWing <: AbstractWing - n_panels::Int16 - n_groups::Int16 - spanwise_distribution::PanelDistribution - panel_props::PanelProperties - spanwise_direction::MVec3 - sections::Vector{Section} - refined_sections::Vector{Section} - remove_nan::Bool - - # Additional fields for RamAirWing - non_deformed_sections::Vector{Section} - mass::Float64 - gamma_tip::Float64 - inertia_tensor::Matrix{Float64} - T_cad_body::MVec3 - R_cad_body::MMat3 - radius::Float64 - le_interp::NTuple{3, Extrapolation} - te_interp::NTuple{3, Extrapolation} - area_interp::Extrapolation - theta_dist::Vector{Float64} - delta_dist::Vector{Float64} - cache::Vector{PreallocationTools.LazyBufferCache{typeof(identity), typeof(identity)}} -end + ObjWing(obj_path, dat_path; kwargs...) -""" - RamAirWing(obj_path, dat_path; kwargs...) - -Create a ram-air wing model from 3D geometry and airfoil data files. +Create a deformable wing model from 3D geometry (.obj) and airfoil data (.dat) files. This constructor builds a complete aerodynamic model by: -1. Loading or generating wing geometry from the .obj file -2. Creating aerodynamic polars from the airfoil .dat file +1. Loading wing geometry from the .obj file +2. Creating aerodynamic polars from the airfoil .dat file (or loading existing) 3. Computing inertial properties and coordinate transformations 4. Setting up control surfaces and panel distribution +The resulting Wing supports deformation through group_deform! and deform! functions. + # Arguments - `obj_path`: Path to .obj file containing 3D wing geometry - `dat_path`: Path to .dat file containing 2D airfoil profile @@ -389,32 +340,34 @@ This constructor builds a complete aerodynamic model by: - `remove_nan=true`: Interpolate NaN values in aerodynamic data - `alpha_range=deg2rad.(-5:1:20)`: Angle of attack range for polars (rad) - `delta_range=deg2rad.(-5:1:20)`: Trailing edge deflection range for polars (rad) -- prn=true: if info messages shall be printed +- `prn=true`: Print informational messages # Returns -A fully initialized `RamAirWing` instance ready for aerodynamic simulation. +A fully initialized `Wing` instance ready for aerodynamic simulation with deformation support. # Example ```julia -# Create a ram-air wing from geometry files -wing = RamAirWing( +# Create a deformable wing from geometry files +wing = ObjWing( "path/to/wing.obj", "path/to/airfoil.dat"; mass=1.5, n_panels=40, n_groups=4 ) + +# Apply deformation +group_deform!(wing, deg2rad.([5, 10, 5, 0]), deg2rad.([-5, 0, -5, 0])) ``` """ -function RamAirWing( - obj_path, dat_path; - crease_frac=0.9, wind_vel=10., mass=1.0, - n_panels=56, n_sections=n_panels+1, n_groups=4, spanwise_distribution=UNCHANGED, +function ObjWing( + obj_path, dat_path; + crease_frac=0.9, wind_vel=10., mass=1.0, + n_panels=56, n_sections=n_panels+1, n_groups=4, spanwise_distribution=UNCHANGED, spanwise_direction=[0.0, 1.0, 0.0], remove_nan=true, align_to_principal=false, alpha_range=deg2rad.(-5:1:20), delta_range=deg2rad.(-5:1:20), prn=true, - interp_steps=n_sections # TODO: check if interpolations are still needed + interp_steps=n_sections ) - !(n_groups == 0 || n_panels % n_groups == 0) && throw(ArgumentError("Number of panels should be divisible by number of groups")) !isapprox(spanwise_direction, [0.0, 1.0, 0.0]) && throw(ArgumentError("Spanwise direction has to be [0.0, 1.0, 0.0], not $spanwise_direction")) @@ -436,7 +389,7 @@ function RamAirWing( if align_to_principal inertia_tensor, R_cad_body = calc_inertia_y_rotation(inertia_tensor) else - R_cad_body = I(3) + R_cad_body = Matrix{Float64}(I, 3, 3) end circle_center_z, radius, gamma_tip = find_circle_center_and_radius(vertices) le_interp, te_interp, area_interp = create_interpolations(vertices, circle_center_z, radius, gamma_tip, R_cad_body; interp_steps) @@ -446,7 +399,7 @@ function RamAirWing( if !ispath(cl_polar_path) || !ispath(cd_polar_path) || !ispath(cm_polar_path) width = 2gamma_tip * radius area = area_interp(gamma_tip) - create_polars(; dat_path, cl_polar_path, cd_polar_path, cm_polar_path, wind_vel, + create_polars(; dat_path, cl_polar_path, cd_polar_path, cm_polar_path, wind_vel, area, width, crease_frac, alpha_range, delta_range, remove_nan) end @@ -459,7 +412,7 @@ function RamAirWing( any(isnan.(cd_matrix)) && interpolate_matrix_nans!(cd_matrix; prn) any(isnan.(cm_matrix)) && interpolate_matrix_nans!(cm_matrix; prn) end - + # Create sections sections = Section[] refined_sections = Section[] @@ -474,12 +427,13 @@ function RamAirWing( end panel_props = PanelProperties{n_panels}() - cache = [LazyBufferCache()] + cache = [PreallocationTools.LazyBufferCache()] - RamAirWing(n_panels, n_groups, spanwise_distribution, panel_props, spanwise_direction, sections, - refined_sections, remove_nan, non_deformed_sections, + Wing(n_panels, n_groups, spanwise_distribution, panel_props, MVec3(spanwise_direction), + sections, refined_sections, remove_nan, + non_deformed_sections, zeros(n_panels), zeros(n_panels), mass, gamma_tip, inertia_tensor, T_cad_body, R_cad_body, radius, - le_interp, te_interp, area_interp, zeros(n_panels), zeros(n_panels), cache) + le_interp, te_interp, area_interp, cache) catch e if e isa BoundsError @@ -488,110 +442,3 @@ function RamAirWing( rethrow(e) end end - -""" - group_deform!(wing::RamAirWing, theta_angles::AbstractVector, delta_angles::AbstractVector) - -Distribute control angles across wing panels and apply smoothing using a moving average filter. - -# Arguments -- `wing::RamAirWing`: The wing to deform -- `theta_angles::AbstractVector`: Twist angles in radians for each control section -- `delta_angles::AbstractVector`: Trailing edge deflection angles in radians for each control section -- `smooth::Bool`: Wether to apply smoothing or not - -# Algorithm -1. Distributes each control input to its corresponding group of panels -2. Applies moving average smoothing with window size based on control group size - -# Errors -- Throws `ArgumentError` if panel count is not divisible by the number of control inputs - -# Returns -- `nothing` (modifies wing in-place) -""" -function group_deform!(wing::RamAirWing, theta_angles=nothing, delta_angles=nothing; smooth=false) - !isnothing(theta_angles) && !(wing.n_panels % length(theta_angles) == 0) && - throw(ArgumentError("Number of angles has to be a multiple of number of panels")) - !isnothing(delta_angles) && !(wing.n_panels % length(delta_angles) == 0) && - throw(ArgumentError("Number of angles has to be a multiple of number of panels")) - isnothing(theta_angles) && isnothing(delta_angles) && return nothing - - n_panels = wing.n_panels - theta_dist = wing.theta_dist - delta_dist = wing.delta_dist - n_angles = isnothing(theta_angles) ? length(delta_angles) : length(theta_angles) - - dist_idx = 0 - for angle_idx in 1:n_angles - for _ in 1:(wing.n_panels ÷ n_angles) - dist_idx += 1 - !isnothing(theta_angles) && (theta_dist[dist_idx] = theta_angles[angle_idx]) - !isnothing(delta_angles) && (delta_dist[dist_idx] = delta_angles[angle_idx]) - end - end - @assert (dist_idx == wing.n_panels) - - if smooth - window_size = wing.n_panels ÷ n_angles - if n_panels > window_size - smoothed = wing.cache[1][theta_dist] - - if !isnothing(theta_angles) - smoothed .= theta_dist - for i in (window_size÷2 + 1):(n_panels - window_size÷2) - @views smoothed[i] = mean(theta_dist[(i - window_size÷2):(i + window_size÷2)]) - end - theta_dist .= smoothed - end - - if !isnothing(delta_angles) - smoothed .= delta_dist - for i in (window_size÷2 + 1):(n_panels - window_size÷2) - @views smoothed[i] = mean(delta_dist[(i - window_size÷2):(i + window_size÷2)]) - end - delta_dist .= smoothed - end - end - end - deform!(wing) - return nothing -end - -""" - deform!(wing::RamAirWing, theta_dist::AbstractVector, delta_dist::AbstractVector; width) - -Deform wing by applying theta and delta distributions. - -# Arguments -- `wing`: RamAirWing to deform -- `theta_dist`: the angle distribution between of the kite and the body x-axis in radians of each panel -- `delta_dist`: the deformation of the trailing edges of each panel - -# Effects -Updates wing.sections with deformed geometry -""" -function deform!(wing::RamAirWing, theta_dist::AbstractVector, delta_dist::AbstractVector) - !(length(theta_dist) == wing.n_panels) && throw(ArgumentError("theta_dist and panels are of different lengths")) - !(length(delta_dist) == wing.n_panels) && throw(ArgumentError("delta_dist and panels are of different lengths")) - wing.theta_dist .= theta_dist - wing.delta_dist .= delta_dist - - deform!(wing) -end - -function deform!(wing::RamAirWing) - local_y = zeros(MVec3) - chord = zeros(MVec3) - normal = zeros(MVec3) - - for i in 1:wing.n_panels - section1 = wing.non_deformed_sections[i] - section2 = wing.non_deformed_sections[i+1] - local_y .= normalize(section1.LE_point - section2.LE_point) - chord .= section1.TE_point .- section1.LE_point - normal .= chord × local_y - @. wing.sections[i].TE_point = section1.LE_point + cos(wing.theta_dist[i]) * chord - sin(wing.theta_dist[i]) * normal - end - return nothing -end diff --git a/src/solver.jl b/src/solver.jl index 8b2d75fd..9bce66ae 100644 --- a/src/solver.jl +++ b/src/solver.jl @@ -654,15 +654,15 @@ function smooth_circulation!( end """ - linearize(solver::Solver, body_aero::BodyAerodynamics, wing::RamAirWing, y::Vector{T}; + linearize(solver::Solver, body_aero::BodyAerodynamics, wing::Wing, y::Vector{T}; theta_idxs=1:4, delta_idxs=nothing, va_idxs=nothing, omega_idxs=nothing, kwargs...) where T -Compute the Jacobian matrix for a ram air wing around an operating point using finite differences. +Compute the Jacobian matrix for a deformable wing around an operating point using finite differences. # Arguments - `solver`: VSM solver instance (must be initialized) - `body_aero`: Aerodynamic body representation -- `wing`: RamAirWing model to linearize +- `wing`: Wing model to linearize (must support deformation, i.e., created with ObjWing()) - `y`: Input vector at operating point, containing a combination of control angles and velocities # Keyword Arguments @@ -679,7 +679,7 @@ Compute the Jacobian matrix for a ram air wing around an operating point using f # Example ```julia # Initialize wing and solver -wing = RamAirWing("path/to/body.obj", "path/to/foil.dat") +wing = ObjWing("path/to/body.obj", "path/to/foil.dat") body_aero = BodyAerodynamics([wing]) solver = Solver(body_aero) diff --git a/src/wing_geometry.jl b/src/wing_geometry.jl index bb1f5e06..02f7a308 100644 --- a/src/wing_geometry.jl +++ b/src/wing_geometry.jl @@ -192,7 +192,7 @@ end Represents a wing composed of multiple sections with aerodynamic properties. -# Fields +# Core Fields (all wings) - `n_panels::Int16`: Number of panels in aerodynamic mesh - `n_groups::Int16`: Number of panel groups - `spanwise_distribution`::PanelDistribution: [PanelDistribution](@ref) @@ -201,6 +201,23 @@ Represents a wing composed of multiple sections with aerodynamic properties. - `refined_sections::Vector{Section}`: Vector of refined wing sections, see: [Section](@ref) - `remove_nan::Bool`: Wether to remove the NaNs from interpolations or not +# Deformation Fields (optional, for deformable wings) +- `non_deformed_sections::Vector{Section}`: Original undeformed sections +- `theta_dist::Vector{Float64}`: Panel twist angle distribution +- `delta_dist::Vector{Float64}`: Trailing edge deflection distribution + +# Physical Properties (optional, for OBJ-based wings) +- `mass::Float64`: Total wing mass in kg (0.0 if not applicable) +- `gamma_tip::Float64`: Angular extent from center to wing tip (0.0 if not applicable) +- `inertia_tensor::Matrix{Float64}`: 3x3 inertia tensor (empty if not applicable) +- `T_cad_body::MVec3`: Translation from CAD to body frame (zeros if not applicable) +- `R_cad_body::MMat3`: Rotation from CAD to body frame (identity if not applicable) +- `radius::Float64`: Wing curvature radius (0.0 if not applicable) +- `le_interp::Union{Nothing, NTuple{3, Extrapolation}}`: Leading edge interpolation +- `te_interp::Union{Nothing, NTuple{3, Extrapolation}}`: Trailing edge interpolation +- `area_interp::Union{Nothing, Extrapolation}`: Area interpolation +- `cache::Vector{PreallocationTools.LazyBufferCache{typeof(identity), typeof(identity)}}`: Preallocated buffers + """ mutable struct Wing <: AbstractWing n_panels::Int16 @@ -211,6 +228,23 @@ mutable struct Wing <: AbstractWing sections::Vector{Section} refined_sections::Vector{Section} remove_nan::Bool + + # Deformation fields + non_deformed_sections::Vector{Section} + theta_dist::Vector{Float64} + delta_dist::Vector{Float64} + + # Physical properties (OBJ-based wings) + mass::Float64 + gamma_tip::Float64 + inertia_tensor::Matrix{Float64} + T_cad_body::MVec3 + R_cad_body::MMat3 + radius::Float64 + le_interp::Union{Nothing, NTuple{3, Extrapolation}} + te_interp::Union{Nothing, NTuple{3, Extrapolation}} + area_interp::Union{Nothing, Extrapolation} + cache::Vector{PreallocationTools.LazyBufferCache{typeof(identity), typeof(identity)}} end """ @@ -220,8 +254,8 @@ end spanwise_direction::PosVector=MVec3([0.0, 1.0, 0.0]), remove_nan::Bool=true) -Constructor for a [Wing](@ref) struct with default values that initializes the sections -and refined sections as empty arrays. +Constructor for a [Wing](@ref) struct with default values that initializes the sections +and refined sections as empty arrays. Creates a basic wing suitable for YAML-based construction. # Parameters - `n_panels::Int`: Number of panels in aerodynamic mesh @@ -237,12 +271,23 @@ function Wing(n_panels::Int; remove_nan=true) !(n_groups == 0 || n_panels % n_groups == 0) && throw(ArgumentError("Number of panels should be divisible by number of groups")) panel_props = PanelProperties{n_panels}() - Wing(n_panels, n_groups, spanwise_distribution, panel_props, spanwise_direction, Section[], Section[], remove_nan) + + # Initialize with default/empty values for optional fields + Wing( + n_panels, n_groups, spanwise_distribution, panel_props, spanwise_direction, + Section[], Section[], remove_nan, + # Deformation fields + Section[], zeros(n_panels), zeros(n_panels), + # Physical properties (defaults for non-OBJ wings) + 0.0, 0.0, zeros(0, 0), zeros(MVec3), Matrix{Float64}(I, 3, 3), + 0.0, nothing, nothing, nothing, + PreallocationTools.LazyBufferCache{typeof(identity), typeof(identity)}[] + ) end function reinit!(wing::AbstractWing) refine_aerodynamic_mesh!(wing) - + # Calculate panel properties update_panel_properties!( wing.panel_props, @@ -252,6 +297,148 @@ function reinit!(wing::AbstractWing) return nothing end +""" + group_deform!(wing::Wing, theta_angles=nothing, delta_angles=nothing; smooth=false) + +Distribute control angles across wing panels and optionally apply smoothing. + +For wings that support deformation (OBJ-based wings with non_deformed_sections), this +distributes theta_angles and delta_angles to panel groups and applies deformation. +For wings without deformation support (YAML-based), this is a no-op that only succeeds +if both angle inputs are nothing. + +# Arguments +- `wing::Wing`: The wing to deform +- `theta_angles::AbstractVector`: Twist angles in radians for each control group (or nothing) +- `delta_angles::AbstractVector`: Trailing edge deflection angles in radians (or nothing) +- `smooth::Bool`: Whether to apply moving average smoothing + +# Algorithm +1. Distributes each control input to its corresponding group of panels +2. Optionally applies moving average smoothing with window based on group size +3. Calls deform! to update wing geometry + +# Errors +- Throws `ArgumentError` if wing doesn't support deformation but angles are provided +- Throws `ArgumentError` if panel count is not divisible by number of control inputs + +# Returns +- `nothing` (modifies wing in-place) +""" +function group_deform!(wing::Wing, theta_angles=nothing, delta_angles=nothing; smooth=false) + # Check if deformation is supported + can_deform = !isempty(wing.non_deformed_sections) + + # If no deformation requested, just return + isnothing(theta_angles) && isnothing(delta_angles) && return nothing + + # If deformation requested but not supported, throw error + if !can_deform + throw(ArgumentError("This Wing does not support deformation. Only OBJ-based wings created with ObjWing() can be deformed.")) + end + + # Validate inputs + !isnothing(theta_angles) && !(wing.n_panels % length(theta_angles) == 0) && + throw(ArgumentError("Number of theta_angles has to be a divisor of number of panels")) + !isnothing(delta_angles) && !(wing.n_panels % length(delta_angles) == 0) && + throw(ArgumentError("Number of delta_angles has to be a divisor of number of panels")) + + n_panels = wing.n_panels + theta_dist = wing.theta_dist + delta_dist = wing.delta_dist + n_angles = isnothing(theta_angles) ? length(delta_angles) : length(theta_angles) + + # Distribute angles to panels + dist_idx = 0 + for angle_idx in 1:n_angles + for _ in 1:(wing.n_panels ÷ n_angles) + dist_idx += 1 + !isnothing(theta_angles) && (theta_dist[dist_idx] = theta_angles[angle_idx]) + !isnothing(delta_angles) && (delta_dist[dist_idx] = delta_angles[angle_idx]) + end + end + @assert (dist_idx == wing.n_panels) + + # Apply smoothing if requested + if smooth + window_size = wing.n_panels ÷ n_angles + if n_panels > window_size + smoothed = wing.cache[1][theta_dist] + + if !isnothing(theta_angles) + smoothed .= theta_dist + for i in (window_size÷2 + 1):(n_panels - window_size÷2) + @views smoothed[i] = mean(theta_dist[(i - window_size÷2):(i + window_size÷2)]) + end + theta_dist .= smoothed + end + + if !isnothing(delta_angles) + smoothed .= delta_dist + for i in (window_size÷2 + 1):(n_panels - window_size÷2) + @views smoothed[i] = mean(delta_dist[(i - window_size÷2):(i + window_size÷2)]) + end + delta_dist .= smoothed + end + end + end + + deform!(wing) + return nothing +end + +""" + deform!(wing::Wing, theta_dist::AbstractVector, delta_dist::AbstractVector) + +Deform wing by applying theta and delta distributions directly. + +# Arguments +- `wing::Wing`: Wing to deform (must support deformation) +- `theta_dist::AbstractVector`: Twist angle in radians for each panel +- `delta_dist::AbstractVector`: Trailing edge deflection for each panel + +# Effects +Updates wing.sections with deformed geometry based on wing.non_deformed_sections +""" +function deform!(wing::Wing, theta_dist::AbstractVector, delta_dist::AbstractVector) + !isempty(wing.non_deformed_sections) || throw(ArgumentError("Wing does not support deformation")) + !(length(theta_dist) == wing.n_panels) && throw(ArgumentError("theta_dist and panels are of different lengths")) + !(length(delta_dist) == wing.n_panels) && throw(ArgumentError("delta_dist and panels are of different lengths")) + wing.theta_dist .= theta_dist + wing.delta_dist .= delta_dist + + deform!(wing) +end + +""" + deform!(wing::Wing) + +Apply stored theta_dist and delta_dist to deform the wing geometry. + +# Arguments +- `wing::Wing`: Wing to deform (must have non_deformed_sections) + +# Effects +Updates wing.sections based on wing.non_deformed_sections and stored distributions +""" +function deform!(wing::Wing) + !isempty(wing.non_deformed_sections) || return nothing + + local_y = zeros(MVec3) + chord = zeros(MVec3) + normal = zeros(MVec3) + + for i in 1:wing.n_panels + section1 = wing.non_deformed_sections[i] + section2 = wing.non_deformed_sections[i+1] + local_y .= normalize(section1.LE_point - section2.LE_point) + chord .= section1.TE_point .- section1.LE_point + normal .= chord × local_y + @. wing.sections[i].TE_point = section1.LE_point + cos(wing.theta_dist[i]) * chord - sin(wing.theta_dist[i]) * normal + end + return nothing +end + """ remove_vector_nans(aero_data) diff --git a/test/body_aerodynamics/test_results.jl b/test/body_aerodynamics/test_results.jl index 2b47dc5b..60d2d4cf 100644 --- a/test/body_aerodynamics/test_results.jl +++ b/test/body_aerodynamics/test_results.jl @@ -31,7 +31,7 @@ if !@isdefined ram_wing_results error("Required data files not found: $body_src or $foil_src") end - ram_wing = RamAirWing(body_path, foil_path; alpha_range=deg2rad.(-1:1), delta_range=deg2rad.(-1:1)) + ram_wing = ObjWing(body_path, foil_path; alpha_range=deg2rad.(-1:1), delta_range=deg2rad.(-1:1)) end @testset "Nonlinear vs Linear - Comprehensive Input Testing" begin diff --git a/test/plotting/test_plotting.jl b/test/plotting/test_plotting.jl index 385abcef..e1f82959 100644 --- a/test/plotting/test_plotting.jl +++ b/test/plotting/test_plotting.jl @@ -29,7 +29,7 @@ if !@isdefined ram_wing foil_src = joinpath(_ram_data_dir, "ram_air_kite_foil.dat") cp(body_src, body_path; force=true) cp(foil_src, foil_path; force=true) - ram_wing = RamAirWing(body_path, foil_path; alpha_range=deg2rad.(-1:1), delta_range=deg2rad.(-1:1)) + ram_wing = ObjWing(body_path, foil_path; alpha_range=deg2rad.(-1:1), delta_range=deg2rad.(-1:1)) end function create_body_aero() diff --git a/test/ram_geometry/test_kite_geometry.jl b/test/ram_geometry/test_kite_geometry.jl index 74b6fd9c..47dee1d4 100644 --- a/test/ram_geometry/test_kite_geometry.jl +++ b/test/ram_geometry/test_kite_geometry.jl @@ -165,9 +165,9 @@ using Serialization @test R_b_p2 ≈ I(3) end - @testset "RamAirWing Construction" begin - wing = RamAirWing(test_obj_path, test_dat_path; remove_nan=true) - + @testset "ObjWing Construction" begin + wing = ObjWing(test_obj_path, test_dat_path; remove_nan=true) + @test wing.n_panels == 56 # Default value @test wing.spanwise_distribution == UNCHANGED @test wing.spanwise_direction ≈ [0.0, 1.0, 0.0] @@ -179,15 +179,15 @@ using Serialization @test !isnan(wing.sections[1].aero_data[4][end]) @test !isnan(wing.sections[1].aero_data[5][end]) - wing = RamAirWing(test_obj_path, test_dat_path; remove_nan=false) + wing = ObjWing(test_obj_path, test_dat_path; remove_nan=false) @test isnan(wing.sections[1].aero_data[3][end]) @test isnan(wing.sections[1].aero_data[4][end]) @test isnan(wing.sections[1].aero_data[5][end]) end @testset "Wing Deformation" begin - # Create a RamAirWing for testing - wing = RamAirWing(test_obj_path, test_dat_path; remove_nan=true) + # Create an ObjWing for testing + wing = ObjWing(test_obj_path, test_dat_path; remove_nan=true) body_aero = BodyAerodynamics([wing]) # Store original TE point for comparison diff --git a/test/solver/test_solver.jl b/test/solver/test_solver.jl index 0dbb9971..084be994 100644 --- a/test/solver/test_solver.jl +++ b/test/solver/test_solver.jl @@ -53,7 +53,7 @@ using Test sol = solve!(solver, body_aero) @test sol isa VSMSolution - @test sol.solver_status == SUCCESS + @test sol.solver_status == FEASIBLE # Verify that group moments are empty @test length(sol.group_moment_dist) == 0 @@ -177,4 +177,47 @@ using Test rm(settings_file; force=true) end end + + @testset "Wing type cannot deform" begin + # Test that regular Wing type (YAML-based) cannot use group_deform! + settings_file = create_temp_wing_settings("solver", "solver_test_wing.yaml"; + alpha=5.0, beta=0.0, wind_speed=10.0, n_groups=2, n_panels=4) + + try + settings = VSMSettings(settings_file) + wing = Wing(settings) + @test wing isa Wing + @test wing.n_groups == 2 + + body_aero = BodyAerodynamics([wing]) + solver = Solver(body_aero, settings) + + va = [10.0, 0.0, 0.0] + set_va!(body_aero, va) + + # Test that trying to use theta angles with Wing throws an error + y = [0.0, 0.0, 10.0, 0.0, 0.0] # 2 theta + 3 va + @test_throws ArgumentError VortexStepMethod.linearize( + solver, + body_aero, + y; + theta_idxs=1:2, + va_idxs=3:5 + ) + + # But linearize should work fine with only velocity (no deformation) + y_velocity_only = [10.0, 0.0, 0.0] + jac, results = VortexStepMethod.linearize( + solver, + body_aero, + y_velocity_only; + theta_idxs=nothing, + va_idxs=1:3 + ) + @test size(jac, 1) == 8 # 6 + 2 group moments + + finally + rm(settings_file; force=true) + end + end end diff --git a/test/wake/test_wake.jl b/test/wake/test_wake.jl index 156e4ec9..b1c45f87 100644 --- a/test/wake/test_wake.jl +++ b/test/wake/test_wake.jl @@ -20,7 +20,7 @@ using VortexStepMethod try # Create wing and body aerodynamics with known good geometry - wing = RamAirWing(body_path, foil_path; n_panels=56) # Use default panels + wing = ObjWing(body_path, foil_path; n_panels=56) # Use default panels body_aero = BodyAerodynamics([wing]) # Test that frozen_wake! doesn't throw errors From 15811702ff937442d915c86bbe5b24e27a34b9c4 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sun, 26 Oct 2025 13:52:56 +0100 Subject: [PATCH 03/86] Restore test --- test/solver/test_solver.jl | 191 ------------------------------------- 1 file changed, 191 deletions(-) diff --git a/test/solver/test_solver.jl b/test/solver/test_solver.jl index 084be994..1d60061a 100644 --- a/test/solver/test_solver.jl +++ b/test/solver/test_solver.jl @@ -29,195 +29,4 @@ using Test rm(settings_file; force=true) end end - - @testset "Solver with n_groups=0" begin - # Test that solver works correctly when n_groups=0 (no group functionality) - settings_file = create_temp_wing_settings("solver", "solver_test_wing.yaml"; - alpha=5.0, beta=0.0, wind_speed=10.0, n_groups=0) - - try - settings = VSMSettings(settings_file) - wing = Wing(settings) - @test wing.n_groups == 0 - - body_aero = BodyAerodynamics([wing]) - solver = Solver(body_aero, settings) - - # Verify solver has zero groups - @test length(solver.sol.group_moment_dist) == 0 - @test length(solver.sol.group_moment_coeff_dist) == 0 - - # Test that solve! works without errors - va = [10.0, 0.0, 0.0] - set_va!(body_aero, va) - sol = solve!(solver, body_aero) - - @test sol isa VSMSolution - @test sol.solver_status == FEASIBLE - - # Verify that group moments are empty - @test length(sol.group_moment_dist) == 0 - @test length(sol.group_moment_coeff_dist) == 0 - - # But force and moment should still be computed - @test !all(sol.force .== 0.0) - @test norm(sol.force) > 0 - - finally - rm(settings_file; force=true) - end - end - - @testset "Linearize with n_groups=0" begin - # Test that linearize works correctly when n_groups=0 - settings_file = create_temp_wing_settings("solver", "solver_test_wing.yaml"; - alpha=5.0, beta=0.0, wind_speed=10.0, n_groups=0, n_panels=4) - - try - settings = VSMSettings(settings_file) - wing = Wing(settings) - @test wing.n_groups == 0 - - body_aero = BodyAerodynamics([wing]) - solver = Solver(body_aero, settings) - - # Set velocity - va = [10.0, 0.0, 0.0] - set_va!(body_aero, va) - - # Test linearize with only velocity (no theta or delta since n_groups=0) - y = va # Only velocity in input vector - jac, results = VortexStepMethod.linearize( - solver, - body_aero, - y; - theta_idxs=nothing, - delta_idxs=nothing, - va_idxs=1:3, - omega_idxs=nothing - ) - - # Results should only have 6 elements (force + moment, no group moments) - @test length(results) == 6 - @test size(jac) == (6, 3) # 6 outputs, 3 inputs (vx, vy, vz) - - # Verify forces are non-zero - @test norm(results[1:3]) > 0 - - # Test that using theta_idxs with n_groups=0 throws an error - @test_throws ArgumentError VortexStepMethod.linearize( - solver, - body_aero, - [0.0, 10.0, 0.0, 0.0]; # Invalid: trying to use theta - theta_idxs=1:1, - va_idxs=2:4 - ) - - # Test that using delta_idxs with n_groups=0 throws an error - @test_throws ArgumentError VortexStepMethod.linearize( - solver, - body_aero, - [0.0, 10.0, 0.0, 0.0]; # Invalid: trying to use delta - delta_idxs=1:1, - va_idxs=2:4 - ) - - finally - rm(settings_file; force=true) - end - end - - @testset "Linearize theta_idxs validation" begin - # Test that theta_idxs length must match n_groups - settings_file = create_temp_wing_settings("solver", "solver_test_wing.yaml"; - alpha=5.0, beta=0.0, wind_speed=10.0, n_groups=2, n_panels=4) - - try - settings = VSMSettings(settings_file) - wing = Wing(settings) - @test wing.n_groups == 2 - - body_aero = BodyAerodynamics([wing]) - solver = Solver(body_aero, settings) - - va = [10.0, 0.0, 0.0] - set_va!(body_aero, va) - - # Test with correct number of theta angles (2) - y_correct = [0.0, 0.0, 10.0, 0.0, 0.0] # 2 theta + 3 va - jac, results = VortexStepMethod.linearize( - solver, - body_aero, - y_correct; - theta_idxs=1:2, - va_idxs=3:5 - ) - @test size(jac, 1) == 8 # 6 + 2 group moments - - # Test with wrong number of theta angles (should throw error) - y_wrong = [0.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0] # 4 theta + 3 va - @test_throws ArgumentError VortexStepMethod.linearize( - solver, - body_aero, - y_wrong; - theta_idxs=1:4, # Wrong: 4 angles but only 2 groups - va_idxs=5:7 - ) - - # Test with wrong number of delta angles - @test_throws ArgumentError VortexStepMethod.linearize( - solver, - body_aero, - y_wrong; - delta_idxs=1:4, # Wrong: 4 angles but only 2 groups - va_idxs=5:7 - ) - - finally - rm(settings_file; force=true) - end - end - - @testset "Wing type cannot deform" begin - # Test that regular Wing type (YAML-based) cannot use group_deform! - settings_file = create_temp_wing_settings("solver", "solver_test_wing.yaml"; - alpha=5.0, beta=0.0, wind_speed=10.0, n_groups=2, n_panels=4) - - try - settings = VSMSettings(settings_file) - wing = Wing(settings) - @test wing isa Wing - @test wing.n_groups == 2 - - body_aero = BodyAerodynamics([wing]) - solver = Solver(body_aero, settings) - - va = [10.0, 0.0, 0.0] - set_va!(body_aero, va) - - # Test that trying to use theta angles with Wing throws an error - y = [0.0, 0.0, 10.0, 0.0, 0.0] # 2 theta + 3 va - @test_throws ArgumentError VortexStepMethod.linearize( - solver, - body_aero, - y; - theta_idxs=1:2, - va_idxs=3:5 - ) - - # But linearize should work fine with only velocity (no deformation) - y_velocity_only = [10.0, 0.0, 0.0] - jac, results = VortexStepMethod.linearize( - solver, - body_aero, - y_velocity_only; - theta_idxs=nothing, - va_idxs=1:3 - ) - @test size(jac, 1) == 8 # 6 + 2 group moments - - finally - rm(settings_file; force=true) - end - end end From df97a2187674f727b2cbb82c1b851baa97a98f23 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Wed, 29 Oct 2025 14:52:52 +0100 Subject: [PATCH 04/86] Not passing bench --- src/body_aerodynamics.jl | 72 ++++++++++++++++++++++++++-------------- 1 file changed, 47 insertions(+), 25 deletions(-) diff --git a/src/body_aerodynamics.jl b/src/body_aerodynamics.jl index 6444a598..9e09f54c 100644 --- a/src/body_aerodynamics.jl +++ b/src/body_aerodynamics.jl @@ -129,13 +129,13 @@ Initialize a BodyAerodynamics struct in-place by setting up panels and coefficie # Returns nothing """ -function reinit!(body_aero::BodyAerodynamics; +function reinit!(body_aero::BodyAerodynamics; init_aero=true, va=[15.0, 0.0, 0.0], omega=zeros(MVec3) ) idx = 1 - vec = zeros(MVec3) + vec = @MVector zeros(3) for wing in body_aero.wings reinit!(wing) panel_props = wing.panel_props @@ -168,8 +168,8 @@ function reinit!(body_aero::BodyAerodynamics; end # Initialize rest of the struct - body_aero.projected_area = sum(wing -> calculate_projected_area(wing), body_aero.wings) - body_aero.stall_angle_list .= calculate_stall_angle_list(body_aero.panels) + body_aero.projected_area = sum(calculate_projected_area, body_aero.wings) + calculate_stall_angle_list!(body_aero.stall_angle_list, body_aero.panels) body_aero.alpha_array .= 0.0 body_aero.v_a_array .= 0.0 body_aero.AIC .= 0.0 @@ -191,21 +191,28 @@ Returns: nothing """ @inline function calculate_AIC_matrices!(body_aero::BodyAerodynamics, model::Model, core_radius_fraction, - va_norm_array, + va_norm_array, va_unit_array) # Determine evaluation point based on model evaluation_point = model == VSM ? :control_point : :aero_center evaluation_point_on_bound = model == LLT - - # Initialize AIC matrices - velocity_induced, tempvel, va_unit, U_2D = zeros(MVec3), zeros(MVec3), zeros(MVec3), zeros(MVec3) + + # Allocate work vectors for this function (separate from those used by child functions) + velocity_induced = @MVector zeros(3) + tempvel = @MVector zeros(3) + va_unit = @MVector zeros(3) + U_2D = @MVector zeros(3) # Calculate influence coefficients for icp in eachindex(body_aero.panels) - ep = getproperty(body_aero.panels[icp], evaluation_point) + panel_icp = body_aero.panels[icp] + ep = evaluation_point == :control_point ? panel_icp.control_point : panel_icp.aero_center for jring in eachindex(body_aero.panels) - va_unit .= @views va_unit_array[jring, :] - filaments = body_aero.panels[jring].filaments + panel_jring = body_aero.panels[jring] + @inbounds for k in 1:3 + va_unit[k] = va_unit_array[jring, k] + end + filaments = panel_jring.filaments va_norm = va_norm_array[jring] calculate_velocity_induced_single_ring_semiinfinite!( velocity_induced, @@ -222,8 +229,8 @@ Returns: nothing # Subtract 2D induced velocity for VSM if icp == jring && model == VSM - calculate_velocity_induced_bound_2D!(U_2D, body_aero.panels[jring], ep, body_aero.work_vectors) - velocity_induced .-= U_2D + calculate_velocity_induced_bound_2D!(U_2D, panel_jring, ep, body_aero.work_vectors) + velocity_induced .-= U_2D end body_aero.AIC[:, icp, jring] .= velocity_induced end @@ -276,19 +283,34 @@ function calculate_stall_angle_list(panels::Vector{Panel}; step_aoa=1.0, stall_angle_if_none_detected=50.0, cl_initial=-10.0) - - aoa_range = deg2rad.(range(begin_aoa, end_aoa, step=step_aoa)) - stall_angles = Float64[] - - for panel in panels + stall_angles = Vector{Float64}(undef, length(panels)) + calculate_stall_angle_list!(stall_angles, panels; + begin_aoa, end_aoa, step_aoa, + stall_angle_if_none_detected, cl_initial) + return stall_angles +end + +function calculate_stall_angle_list!(stall_angles::AbstractVector{Float64}, + panels::Vector{Panel}; + begin_aoa=9.0, + end_aoa=22.0, + step_aoa=1.0, + stall_angle_if_none_detected=50.0, + cl_initial=-10.0) + + # Pre-compute range values to avoid allocation + n_steps = Int(floor((end_aoa - begin_aoa) / step_aoa)) + 1 + + for (idx, panel) in enumerate(panels) # Default stall angle if none found panel_stall = stall_angle_if_none_detected - + # Start with minimum cl cl_old = cl_initial - + # Find stall angle - for aoa in aoa_range + for i in 0:(n_steps-1) + aoa = deg2rad(begin_aoa + i * step_aoa) cl = calculate_cl(panel, aoa) if cl < cl_old panel_stall = aoa @@ -296,11 +318,11 @@ function calculate_stall_angle_list(panels::Vector{Panel}; end cl_old = cl end - - push!(stall_angles, panel_stall) + + stall_angles[idx] = panel_stall end - - return stall_angles + + return nothing end """ From e28c0ced61539c023e5c2e74c22e9efbf407d42b Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Wed, 29 Oct 2025 15:10:21 +0100 Subject: [PATCH 05/86] Working grouping --- README.md | 4 +- bin/install | 2 +- docs/make.jl | 6 -- docs/src/glossary.md | 1 + docs/src/index.md | 4 +- docs/src/tips_and_tricks.md | 32 +++++++++ docs/src/types.md | 1 + examples/Project.toml | 7 ++ examples/bench.jl | 6 -- examples/menu.jl | 5 -- examples/stall_model.jl | 8 +-- scripts/Project.toml | 4 ++ scripts/build_docu.jl | 4 -- src/VortexStepMethod.jl | 12 ++++ src/obj_geometry.jl | 3 +- src/solver.jl | 24 +++++-- src/wing_geometry.jl | 114 +++++++++++++++++++++++++++++---- src/yaml_geometry.jl | 12 ++-- test/Aqua.jl | 5 -- test/Project.toml | 10 +++ test/bench.jl | 5 -- test/bench_solve.jl | 6 -- test/settings/test_settings.jl | 5 -- 23 files changed, 204 insertions(+), 76 deletions(-) create mode 100644 examples/Project.toml create mode 100644 scripts/Project.toml create mode 100644 test/Project.toml diff --git a/README.md b/README.md index de01a449..d93c3a0a 100644 --- a/README.md +++ b/README.md @@ -19,9 +19,9 @@ if you haven't already. On Linux, make sure that Python3 and Matplotlib are inst ``` sudo apt install python3-matplotlib ``` -Furthermore, the packages `TestEnv` and `ControlPlots` must be installed globally: +Furthermore, the package `ControlPlots` must be installed globally: ``` -julia -e 'using Pkg; Pkg.add("TestEnv"); Pkg.add("ControlPlots")' +julia -e 'using Pkg; Pkg.add("ControlPlots")' ``` Before installing this software it is suggested to create a new project, for example like this: diff --git a/bin/install b/bin/install index e4609513..49b359ad 100755 --- a/bin/install +++ b/bin/install @@ -20,7 +20,7 @@ fi export JULIA_PKG_SERVER_REGISTRY_PREFERENCE=eager -julia -e 'using Pkg; Pkg.add("TestEnv"); Pkg.add("ControlPlots")' +julia -e 'using Pkg; Pkg.add("ControlPlots")' julia --project -e 'include("bin/install.jl")' diff --git a/docs/make.jl b/docs/make.jl index 17d42209..677baf72 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,9 +1,3 @@ -using Pkg -if ("TestEnv" ∈ keys(Pkg.project().dependencies)) - if ! ("Documents" ∈ keys(Pkg.project().dependencies)) - using TestEnv; TestEnv.activate() - end -end using ControlPlots using VortexStepMethod using Documenter diff --git a/docs/src/glossary.md b/docs/src/glossary.md index a67c577d..940c6b5d 100644 --- a/docs/src/glossary.md +++ b/docs/src/glossary.md @@ -5,6 +5,7 @@ | AIC | Aerodynamic Influence Coefficient (AIC). The AIC matrix represents the relationship between the induced velocities or pressures on aerodynamic surfaces and the circulation strength or modal deformations of the lifting surfaces.| | inviscid | A fluid flow in which viscosity is considered negligible or zero. This means that there is no internal friction between the fluid layers, and the effects of viscosity on the flow are assumed to be insignificant. | | Panel | Flat surface element in 3D that approximate the contour of the aerodynamic body being studied.| +| Panel Group | A collection of panels whose aerodynamic forces and moments are summed together. Groups can be defined using EQUAL_SIZE (sequential grouping) or REFINE (based on original unrefined structure) methods.| | Section |A wing section, also known as an airfoil or aerofoil, is the cross-sectional shape of an aircraft wing.| | Span | Distance from one wing tip to the other wing tip. | | Polar | The polar typically plots the coefficient of lift (CL) against the coefficient of drag (CD), with the angle of attack as a parameter along the curve. | diff --git a/docs/src/index.md b/docs/src/index.md index fa6d54c1..3310d72c 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -18,9 +18,9 @@ if you haven't already. On Linux, make sure that Python3 and Matplotlib are inst ``` sudo apt install python3-matplotlib ``` -Furthermore, the packages `TestEnv` and `ControlPlots` must be installed globally: +Furthermore, the package `ControlPlots` must be installed globally: ``` -julia -e 'using Pkg; Pkg.add("TestEnv"); Pkg.add("ControlPlots")' +julia -e 'using Pkg; Pkg.add("ControlPlots")' ``` Before installing this software it is suggested to create a new project, for example like this: diff --git a/docs/src/tips_and_tricks.md b/docs/src/tips_and_tricks.md index 64995f34..63cf87d3 100644 --- a/docs/src/tips_and_tricks.md +++ b/docs/src/tips_and_tricks.md @@ -10,6 +10,38 @@ The following bodies can be simulated: To build the geometry of a RAM-air kite, a 3D .obj file can be used as input. In addition a `.dat` file is needed. It should have two columns, one for the `x` and one for the `y` coordinate of the 2D polar that is used. +## Panel Grouping Methods +When creating a wing, you can specify how panels should be grouped for moment and force calculations using the `grouping_method` parameter. Two methods are available: + +### EQUAL_SIZE (Default) +Divides refined panels into equally-sized sequential groups. This is the original behavior. + +```julia +wing = Wing(40; n_groups=4, grouping_method=EQUAL_SIZE) +``` + +In this example, with 40 panels and 4 groups, each group will contain 10 consecutive panels (panels 1-10, 11-20, 21-30, 31-40). + +### REFINE +Groups refined panels back to their original unrefined section. This is useful when you want group moments and forces to represent the original wing structure, regardless of panel refinement. + +```julia +# Create wing with 4 unrefined sections (3 panels) +wing = Wing(40; n_groups=3, grouping_method=REFINE) +add_section!(wing, [0, 5, 0], [1, 5, 0], INVISCID) # Section 1 +add_section!(wing, [0, 2.5, 0], [1, 2.5, 0], INVISCID) # Section 2 +add_section!(wing, [0, 0, 0], [1, 0, 0], INVISCID) # Section 3 +add_section!(wing, [0, -5, 0], [1, -5, 0], INVISCID) # Section 4 +``` + +**Important:** When using `REFINE`, `n_groups` must equal the number of unrefined panels (number of sections - 1). The solver will automatically map each refined panel to its closest original unrefined panel and sum their moments and forces accordingly. + +This is particularly useful for: +- LEI kites where you want loads per rib +- Wings with discrete control surfaces +- Cases where physical structure doesn't align with uniform panel distribution +- Dynamic simulations where you have fewer structural segments than panels needed for accurate VSM aerodynamics. For example, a 6-segment structural model can be combined with 40-panel aerodynamics by using `n_groups=6` and `grouping_method=REFINE` to map aerodynamic loads back to the structural segments. + ## RAM-air kite model If running the example `ram_air_kite.jl` fails, try to run the `cleanup.jl` script and then try again. Background: this example caches the calculated polars. Reading cached polars can fail after an update. diff --git a/docs/src/types.md b/docs/src/types.md index de083b35..9b76a7d0 100644 --- a/docs/src/types.md +++ b/docs/src/types.md @@ -7,6 +7,7 @@ Model WingType AeroModel PanelDistribution +PanelGroupingMethod InitialGammaDistribution SolverStatus ``` diff --git a/examples/Project.toml b/examples/Project.toml new file mode 100644 index 00000000..b94307b9 --- /dev/null +++ b/examples/Project.toml @@ -0,0 +1,7 @@ +[deps] +CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" +ControlPlots = "23c2ee80-7a9e-4350-b264-8e670f12517c" +DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" +LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" +VortexStepMethod = "ed3cd733-9f0f-46a9-93e0-89b8d4998dd9" diff --git a/examples/bench.jl b/examples/bench.jl index 90c41ff1..6c2f8726 100644 --- a/examples/bench.jl +++ b/examples/bench.jl @@ -2,12 +2,6 @@ using LinearAlgebra using ControlPlots using VortexStepMethod -using Pkg - -if !("CSV" ∈ keys(Pkg.project().dependencies)) - using TestEnv - TestEnv.activate() -end # Step 1: Define wing parameters n_panels = 20 # Number of panels diff --git a/examples/menu.jl b/examples/menu.jl index 4454ccee..147990c3 100644 --- a/examples/menu.jl +++ b/examples/menu.jl @@ -1,8 +1,3 @@ -using Pkg -if ! ("ControlPlots" ∈ keys(Pkg.project().dependencies)) - using TestEnv; TestEnv.activate() -end - using ControlPlots using VortexStepMethod using REPL.TerminalMenus diff --git a/examples/stall_model.jl b/examples/stall_model.jl index 6253faca..89f3c0f4 100644 --- a/examples/stall_model.jl +++ b/examples/stall_model.jl @@ -2,10 +2,6 @@ using ControlPlots using LinearAlgebra using VortexStepMethod -using Pkg -if ! ("CSV" ∈ keys(Pkg.project().dependencies)) - using TestEnv; TestEnv.activate() -end using CSV using DataFrames @@ -38,7 +34,9 @@ for row in eachrow(df) end # Create wing geometry -CAD_wing = Wing(n_panels; spanwise_distribution) +# Using REFINE grouping method: n_groups should equal number of unrefined panels (18 sections = 18 panels) +n_groups = length(rib_list) - 1 +CAD_wing = Wing(n_panels; spanwise_distribution, n_groups, grouping_method=REFINE) for rib in rib_list add_section!(CAD_wing, rib[1], rib[2], rib[3], rib[4]) end diff --git a/scripts/Project.toml b/scripts/Project.toml new file mode 100644 index 00000000..f020312d --- /dev/null +++ b/scripts/Project.toml @@ -0,0 +1,4 @@ +[deps] +Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" +LiveServer = "16fef848-5104-11e9-1b77-fb7a48bbb589" +VortexStepMethod = "ed3cd733-9f0f-46a9-93e0-89b8d4998dd9" diff --git a/scripts/build_docu.jl b/scripts/build_docu.jl index f88f437c..f9398642 100644 --- a/scripts/build_docu.jl +++ b/scripts/build_docu.jl @@ -17,8 +17,4 @@ if !("LiveServer" in globaldependencies()) run(`julia -e 'using Pkg; Pkg.add("LiveServer")'`) end -if !("Documenter" ∈ keys(Pkg.project().dependencies)) - using TestEnv - TestEnv.activate() -end using LiveServer; servedocs(launch_browser=true) diff --git a/src/VortexStepMethod.jl b/src/VortexStepMethod.jl index 64a4a657..f3cb531a 100644 --- a/src/VortexStepMethod.jl +++ b/src/VortexStepMethod.jl @@ -37,6 +37,7 @@ export MVec3 export Model, VSM, LLT export AeroModel, LEI_AIRFOIL_BREUKELS, POLAR_VECTORS, POLAR_MATRICES, INVISCID export PanelDistribution, LINEAR, COSINE, COSINE_VAN_GARREL, SPLIT_PROVIDED, UNCHANGED +export PanelGroupingMethod, EQUAL_SIZE, REFINE export InitialGammaDistribution, ELLIPTIC, ZEROS export SolverStatus, FEASIBLE, INFEASIBLE, FAILURE export SolverType, LOOP, NONLIN @@ -138,6 +139,17 @@ Enumeration of the implemented panel distributions. UNCHANGED # Keep original sections end +""" + PanelGroupingMethod EQUAL_SIZE REFINE + +Enumeration of methods for grouping panels. + +# Elements +- EQUAL_SIZE: Divide panels into equally-sized sequential groups +- REFINE: Group refined panels back to their original unrefined section +""" +@enum PanelGroupingMethod EQUAL_SIZE REFINE + """ InitialGammaDistribution ELLIPTIC ZEROS diff --git a/src/obj_geometry.jl b/src/obj_geometry.jl index dec38cb7..1dae4cbc 100644 --- a/src/obj_geometry.jl +++ b/src/obj_geometry.jl @@ -366,7 +366,7 @@ function ObjWing( n_panels=56, n_sections=n_panels+1, n_groups=4, spanwise_distribution=UNCHANGED, spanwise_direction=[0.0, 1.0, 0.0], remove_nan=true, align_to_principal=false, alpha_range=deg2rad.(-5:1:20), delta_range=deg2rad.(-5:1:20), prn=true, - interp_steps=n_sections + interp_steps=n_sections, grouping_method::PanelGroupingMethod=EQUAL_SIZE ) !(n_groups == 0 || n_panels % n_groups == 0) && throw(ArgumentError("Number of panels should be divisible by number of groups")) !isapprox(spanwise_direction, [0.0, 1.0, 0.0]) && throw(ArgumentError("Spanwise direction has to be [0.0, 1.0, 0.0], not $spanwise_direction")) @@ -431,6 +431,7 @@ function ObjWing( Wing(n_panels, n_groups, spanwise_distribution, panel_props, MVec3(spanwise_direction), sections, refined_sections, remove_nan, + grouping_method, Int16[], non_deformed_sections, zeros(n_panels), zeros(n_panels), mass, gamma_tip, inertia_tensor, T_cad_body, R_cad_body, radius, le_interp, te_interp, area_interp, cache) diff --git a/src/solver.jl b/src/solver.jl index 9bce66ae..7f4daec3 100644 --- a/src/solver.jl +++ b/src/solver.jl @@ -302,14 +302,26 @@ function solve!(solver::Solver, body_aero::BodyAerodynamics, gamma_distribution= group_idx = 1 for wing in body_aero.wings if wing.n_groups > 0 - panels_per_group = wing.n_panels ÷ wing.n_groups - for _ in 1:wing.n_groups - for _ in 1:panels_per_group - group_moment_dist[group_idx] += moment_dist[panel_idx] - group_moment_coeff_dist[group_idx] += moment_coeff_dist[panel_idx] + if wing.grouping_method == EQUAL_SIZE + # Original method: divide panels into equally-sized sequential groups + panels_per_group = wing.n_panels ÷ wing.n_groups + for _ in 1:wing.n_groups + for _ in 1:panels_per_group + group_moment_dist[group_idx] += moment_dist[panel_idx] + group_moment_coeff_dist[group_idx] += moment_coeff_dist[panel_idx] + panel_idx += 1 + end + group_idx += 1 + end + elseif wing.grouping_method == REFINE + # REFINE method: group refined panels by their original unrefined section + for local_panel_idx in 1:wing.n_panels + original_section_idx = wing.refined_panel_mapping[local_panel_idx] + group_moment_dist[group_idx + original_section_idx - 1] += moment_dist[panel_idx] + group_moment_coeff_dist[group_idx + original_section_idx - 1] += moment_coeff_dist[panel_idx] panel_idx += 1 end - group_idx += 1 + group_idx += wing.n_groups end else # Skip panels for wings with n_groups=0 diff --git a/src/wing_geometry.jl b/src/wing_geometry.jl index 02f7a308..9536107f 100644 --- a/src/wing_geometry.jl +++ b/src/wing_geometry.jl @@ -229,6 +229,10 @@ mutable struct Wing <: AbstractWing refined_sections::Vector{Section} remove_nan::Bool + # Grouping + grouping_method::PanelGroupingMethod + refined_panel_mapping::Vector{Int16} # Maps each refined panel to its original unrefined section index + # Deformation fields non_deformed_sections::Vector{Section} theta_dist::Vector{Float64} @@ -252,7 +256,8 @@ end n_groups=n_panels, spanwise_distribution::PanelDistribution=LINEAR, spanwise_direction::PosVector=MVec3([0.0, 1.0, 0.0]), - remove_nan::Bool=true) + remove_nan::Bool=true, + grouping_method::PanelGroupingMethod=EQUAL_SIZE) Constructor for a [Wing](@ref) struct with default values that initializes the sections and refined sections as empty arrays. Creates a basic wing suitable for YAML-based construction. @@ -263,19 +268,28 @@ and refined sections as empty arrays. Creates a basic wing suitable for YAML-bas - `spanwise_distribution`::PanelDistribution = LINEAR: [PanelDistribution](@ref) - `spanwise_direction::MVec3` = MVec3([0.0, 1.0, 0.0]): Wing span direction vector - `remove_nan::Bool`: Wether to remove the NaNs from interpolations or not +- `grouping_method::PanelGroupingMethod` = EQUAL_SIZE: Method for grouping panels (EQUAL_SIZE or REFINE) """ function Wing(n_panels::Int; n_groups = n_panels, spanwise_distribution::PanelDistribution=LINEAR, spanwise_direction::PosVector=MVec3([0.0, 1.0, 0.0]), - remove_nan=true) - !(n_groups == 0 || n_panels % n_groups == 0) && throw(ArgumentError("Number of panels should be divisible by number of groups")) + remove_nan=true, + grouping_method::PanelGroupingMethod=EQUAL_SIZE) + # Validate grouping parameters + if grouping_method == EQUAL_SIZE + !(n_groups == 0 || n_panels % n_groups == 0) && throw(ArgumentError("With EQUAL_SIZE grouping, number of panels should be divisible by number of groups")) + end + # Note: For REFINE grouping, validation happens after refinement when we know the number of unrefined sections + panel_props = PanelProperties{n_panels}() # Initialize with default/empty values for optional fields Wing( n_panels, n_groups, spanwise_distribution, panel_props, spanwise_direction, Section[], Section[], remove_nan, + # Grouping + grouping_method, Int16[], # Deformation fields Section[], zeros(n_panels), zeros(n_panels), # Physical properties (defaults for non-OBJ wings) @@ -556,23 +570,25 @@ function refine_aerodynamic_mesh!(wing::AbstractWing) for i in eachindex(wing.sections) reinit!(wing.refined_sections[i], wing.sections[i]) end + compute_refined_panel_mapping!(wing) return nothing end @debug "Refining aerodynamic mesh from $(length(wing.sections)) sections to $n_sections sections." - + # Handle two-section case if n_sections == 2 reinit!(wing.refined_sections[1], LE[1,:], TE[1,:], aero_model[1], aero_data[1]) reinit!(wing.refined_sections[2], LE[end,:], TE[end,:], aero_model[end], aero_data[end]) + compute_refined_panel_mapping!(wing) return nothing end - + # Handle different distribution types if wing.spanwise_distribution == SPLIT_PROVIDED - return refine_mesh_by_splitting_provided_sections!(wing) + refine_mesh_by_splitting_provided_sections!(wing) elseif wing.spanwise_distribution in (LINEAR, COSINE, COSINE_VAN_GARREL) - return refine_mesh_for_linear_cosine_distribution!( + refine_mesh_for_linear_cosine_distribution!( wing, 1, wing.spanwise_distribution, @@ -585,6 +601,80 @@ function refine_aerodynamic_mesh!(wing::AbstractWing) else throw(ArgumentError("Unsupported spanwise panel distribution: $(wing.spanwise_distribution)")) end + + # Compute panel mapping by finding closest unrefined panel for each refined panel + compute_refined_panel_mapping!(wing) + + # Validate REFINE grouping method + if wing.grouping_method == REFINE && wing.n_groups > 0 + n_unrefined_panels = length(wing.sections) - 1 + if wing.n_groups != n_unrefined_panels + throw(ArgumentError( + "With REFINE grouping method, n_groups ($(wing.n_groups)) must equal " * + "the number of unrefined panels ($n_unrefined_panels). " * + "The wing has $(length(wing.sections)) unrefined sections, forming $n_unrefined_panels panels." + )) + end + end + + return nothing +end + + +""" + compute_refined_panel_mapping!(wing::AbstractWing) + +Compute the mapping from refined panels to unrefined panels by finding +the closest unrefined panel for each refined panel (based on panel center distance). +This is non-allocating and works after refinement is complete. +""" +function compute_refined_panel_mapping!(wing::AbstractWing) + n_unrefined_sections = length(wing.sections) + n_refined_panels = wing.n_panels + + # Handle case where no refinement occurred + if n_unrefined_sections == n_refined_panels + 1 + wing.refined_panel_mapping = Int16[i for i in 1:n_refined_panels] + return nothing + end + + # Ensure mapping array is allocated + if length(wing.refined_panel_mapping) != n_refined_panels + wing.refined_panel_mapping = zeros(Int16, n_refined_panels) + end + + # Compute centers of unrefined panels + n_unrefined_panels = n_unrefined_sections - 1 + unrefined_centers = Vector{MVec3}(undef, n_unrefined_panels) + for i in 1:n_unrefined_panels + le_mid = (wing.sections[i].LE_point + wing.sections[i+1].LE_point) / 2 + te_mid = (wing.sections[i].TE_point + wing.sections[i+1].TE_point) / 2 + unrefined_centers[i] = MVec3((le_mid + te_mid) / 2) + end + + # For each refined panel, find closest unrefined panel + for refined_panel_idx in 1:n_refined_panels + le_mid = (wing.refined_sections[refined_panel_idx].LE_point + + wing.refined_sections[refined_panel_idx+1].LE_point) / 2 + te_mid = (wing.refined_sections[refined_panel_idx].TE_point + + wing.refined_sections[refined_panel_idx+1].TE_point) / 2 + refined_center = MVec3((le_mid + te_mid) / 2) + + # Find closest unrefined panel + min_dist = Inf + closest_idx = 1 + for unrefined_panel_idx in 1:n_unrefined_panels + dist = norm(refined_center - unrefined_centers[unrefined_panel_idx]) + if dist < min_dist + min_dist = dist + closest_idx = unrefined_panel_idx + end + end + + wing.refined_panel_mapping[refined_panel_idx] = Int16(closest_idx) + end + + return nothing end @@ -736,7 +826,7 @@ function refine_mesh_for_linear_cosine_distribution!( target_length = target_lengths[i] # Find segment index - section_index = searchsortedlast(qc_cum_length, target_length) + section_index = searchsortedlast(qc_cum_length, target_length) section_index = clamp(section_index, 1, length(qc_cum_length)-1) # 4. Calculate weights @@ -747,7 +837,7 @@ function refine_mesh_for_linear_cosine_distribution!( right_weight = t # 5. Calculate quarter chord point - new_quarter_chord[i,:] = quarter_chord[section_index,:] + + new_quarter_chord[i,:] = quarter_chord[section_index,:] + t .* (quarter_chord[section_index+1,:] - quarter_chord[section_index,:]) # 6. Calculate chord vectors @@ -899,10 +989,10 @@ function refine_mesh_by_splitting_provided_sections!(wing::AbstractWing) # Add left section of pair reinit!(wing.refined_sections[idx], wing.sections[left_section_index]) idx += 1 - + # Calculate new sections for this pair num_new_sections = new_sections_per_pair + (left_section_index <= remaining ? 1 : 0) - + if num_new_sections > 0 # Prepare pair data LE_pair = hcat(LE[left_section_index], LE[left_section_index + 1])' @@ -915,7 +1005,7 @@ function refine_mesh_by_splitting_provided_sections!(wing::AbstractWing) aero_data[left_section_index], aero_data[left_section_index + 1] ] - + # Generate sections for this pair idx = refine_mesh_for_linear_cosine_distribution!( wing, diff --git a/src/yaml_geometry.jl b/src/yaml_geometry.jl index 3ba618f5..42a82199 100644 --- a/src/yaml_geometry.jl +++ b/src/yaml_geometry.jl @@ -188,7 +188,8 @@ function Wing( spanwise_distribution=LINEAR, spanwise_direction=[0.0, 1.0, 0.0], remove_nan=true, - prn=false + prn=false, + grouping_method::PanelGroupingMethod=EQUAL_SIZE ) !(n_groups == 0 || n_panels % n_groups == 0) && throw(ArgumentError("Number of panels should be divisible by number of groups")) !isapprox(spanwise_direction, [0.0, 1.0, 0.0]) && throw(ArgumentError("Spanwise direction has to be [0.0, 1.0, 0.0], not $spanwise_direction")) @@ -236,11 +237,12 @@ function Wing( end # Create Wing using the standard constructor - wing = Wing(n_panels; - n_groups=n_groups, + wing = Wing(n_panels; + n_groups=n_groups, spanwise_distribution=spanwise_distribution, - spanwise_direction=MVec3(spanwise_direction), - remove_nan=remove_nan + spanwise_direction=MVec3(spanwise_direction), + remove_nan=remove_nan, + grouping_method=grouping_method ) # Parse sections and populate wing diff --git a/test/Aqua.jl b/test/Aqua.jl index e16c0cc9..7a885062 100644 --- a/test/Aqua.jl +++ b/test/Aqua.jl @@ -1,8 +1,3 @@ -using Pkg -if ! ("Aqua" ∈ keys(Pkg.project().dependencies)) - using TestEnv; TestEnv.activate() -end - using Aqua, VortexStepMethod, Test @testset "Aqua.jl" begin Aqua.test_all( diff --git a/test/Project.toml b/test/Project.toml new file mode 100644 index 00000000..5354caa3 --- /dev/null +++ b/test/Project.toml @@ -0,0 +1,10 @@ +[deps] +Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" +BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" +CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" +ControlPlots = "23c2ee80-7a9e-4350-b264-8e670f12517c" +DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" +Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" +Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +VortexStepMethod = "ed3cd733-9f0f-46a9-93e0-89b8d4998dd9" diff --git a/test/bench.jl b/test/bench.jl index 5acfb95f..88172d69 100644 --- a/test/bench.jl +++ b/test/bench.jl @@ -1,8 +1,3 @@ -using Pkg -if !("BenchmarkTools" ∈ keys(Pkg.project().dependencies)) - using TestEnv - TestEnv.activate() -end using BenchmarkTools using StaticArrays using VortexStepMethod diff --git a/test/bench_solve.jl b/test/bench_solve.jl index 1abe47d7..dc8c4590 100644 --- a/test/bench_solve.jl +++ b/test/bench_solve.jl @@ -6,12 +6,6 @@ using VortexStepMethod using BenchmarkTools using Test -using Pkg - -if !("CSV" ∈ keys(Pkg.project().dependencies)) - using TestEnv - TestEnv.activate() -end # Step 1: Define wing parameters n_panels = 20 # Number of panels diff --git a/test/settings/test_settings.jl b/test/settings/test_settings.jl index c7412894..33ccd7a7 100644 --- a/test/settings/test_settings.jl +++ b/test/settings/test_settings.jl @@ -1,8 +1,3 @@ -using Pkg -if ! ("Test" ∈ keys(Pkg.project().dependencies)) - using TestEnv; TestEnv.activate() -end - using VortexStepMethod using Test From c27d1572e3da954dfa43459bceec52c69a4e6070 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Wed, 29 Oct 2025 15:46:51 +0100 Subject: [PATCH 06/86] Working tests except aqua --- Project.toml | 22 ---- examples/stall_model.jl | 16 +-- test/Project.toml | 23 +++- test/wing_geometry/test_wing_geometry.jl | 153 +++++++++++++++++++++++ 4 files changed, 184 insertions(+), 30 deletions(-) diff --git a/Project.toml b/Project.toml index 6841b218..29000957 100644 --- a/Project.toml +++ b/Project.toml @@ -38,50 +38,28 @@ VortexStepMethodControlPlotsExt = "ControlPlots" VortexStepMethodMakieExt = "Makie" [compat] -Aqua = "0.8" -BenchmarkTools = "1" -CSV = "0.10" Colors = "0.13" -ControlPlots = "0.2.5" -DataFrames = "1.7" DefaultApplication = "1" DelimitedFiles = "1" DifferentiationInterface = "0.7.4" -Documenter = "1.8" FiniteDiff = "2.27.0" Interpolations = "0.15, 0.16" LaTeXStrings = "1" LinearAlgebra = "1" Logging = "1" -Makie = "0.24.6" Measures = "0.3" NonlinearSolve = "4.8.0" Parameters = "0.12" Pkg = "1" PreallocationTools = "0.4.31" PrecompileTools = "1.2.1" -Random = "1.10.0" RecursiveArrayTools = "3 - 3.36.0" SciMLBase = "2.77.0" Serialization = "1" StaticArrays = "1" Statistics = "1" StructMapping = "0.2.3" -Test = "1" Timers = "0.1" Xfoil = "1.1.0" YAML = "0.4.13" julia = "1.10, 1.11" - -[extras] -Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" -BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" -CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" -ControlPlots = "23c2ee80-7a9e-4350-b264-8e670f12517c" -DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" -Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" -Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" -Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" - -[targets] -test = ["Test", "DataFrames", "CSV", "Documenter", "BenchmarkTools", "ControlPlots", "Aqua", "Random"] diff --git a/examples/stall_model.jl b/examples/stall_model.jl index 89f3c0f4..78fb28fe 100644 --- a/examples/stall_model.jl +++ b/examples/stall_model.jl @@ -107,21 +107,23 @@ path_cfd_lebesque = joinpath( "V3_CL_CD_RANS_Lebesque_2024_Rey_300e4.csv" ) +# Only include literature data if file exists +literature_paths = isfile(path_cfd_lebesque) ? [path_cfd_lebesque] : String[] +labels = isfile(path_cfd_lebesque) ? + ["VSM CAD 19ribs", "VSM CAD 19ribs , with stall correction", "CFD_Lebesque Rey 30e5"] : + ["VSM CAD 19ribs", "VSM CAD 19ribs , with stall correction"] + PLOT && plot_polars( [vsm_solver, VSM_with_stall_correction], [body_aero, body_aero], - [ - "VSM CAD 19ribs", - "VSM CAD 19ribs , with stall correction", - "CFD_Lebesque Rey 30e5" - ]; - literature_path_list=[path_cfd_lebesque], + labels; + literature_path_list=literature_paths, angle_range=range(0, 25, length=25), angle_type="angle_of_attack", angle_of_attack=0, side_slip=0, v_a=10, - title="tutorial_testing_stall_model_n_panels_$(n_panels)_distribution_$(spanwise_distribution)", + title="tutorial_testing_stall_model_n_panels_$(n_panels)_distribution_$(spanwise_distribution)_grouping_$(CAD_wing.grouping_method)", data_type=".pdf", save_path=joinpath(save_folder, "polars"), is_save=true, diff --git a/test/Project.toml b/test/Project.toml index 5354caa3..32eda93f 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -5,6 +5,27 @@ CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" ControlPlots = "23c2ee80-7a9e-4350-b264-8e670f12517c" DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" +Interpolations = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59" +LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +Serialization = "9e88b42a-f829-5b0c-bbe9-9e923198166b" +StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" +Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" -VortexStepMethod = "ed3cd733-9f0f-46a9-93e0-89b8d4998dd9" +YAML = "ddb6d928-2868-570f-bddf-ab3f9cf99eb6" + +[compat] +Aqua = "0.8" +BenchmarkTools = "1" +CSV = "0.10" +ControlPlots = "0.2.5" +DataFrames = "1.7" +Documenter = "1.8" +LinearAlgebra = "1" +Logging = "1" +Random = "1.10.0" +StaticArrays = "1" +Statistics = "1" +Test = "1" +YAML = "0.4.13" diff --git a/test/wing_geometry/test_wing_geometry.jl b/test/wing_geometry/test_wing_geometry.jl index d2d01f0f..ddb8ae25 100644 --- a/test/wing_geometry/test_wing_geometry.jl +++ b/test/wing_geometry/test_wing_geometry.jl @@ -332,4 +332,157 @@ end @test section.aero_model == INVISCID end end + + @testset "REFINE grouping panel mapping" begin + # Test that refined panel mapping actually maps each panel to its closest unrefined panel + + @testset "LINEAR distribution" begin + n_panels = 20 + span = 10.0 + + wing = Wing(n_panels; spanwise_distribution=LINEAR, n_groups=2, grouping_method=REFINE) + # 3 sections = 2 unrefined panels + add_section!(wing, [0.0, span/2, 0.0], [1.0, span/2, 0.0], INVISCID) + add_section!(wing, [0.0, 0.0, 0.0], [1.0, 0.0, 0.0], INVISCID) + add_section!(wing, [0.0, -span/2, 0.0], [1.0, -span/2, 0.0], INVISCID) + + refine_aerodynamic_mesh!(wing) + + @test length(wing.refined_panel_mapping) == n_panels + + # Manually verify each refined panel is mapped to its closest unrefined panel + n_unrefined_panels = length(wing.sections) - 1 + for refined_panel_idx in 1:n_panels + # Calculate refined panel center + le_mid = (wing.refined_sections[refined_panel_idx].LE_point + + wing.refined_sections[refined_panel_idx+1].LE_point) / 2 + te_mid = (wing.refined_sections[refined_panel_idx].TE_point + + wing.refined_sections[refined_panel_idx+1].TE_point) / 2 + refined_center = (le_mid + te_mid) / 2 + + # Find closest unrefined panel manually + min_dist = Inf + closest_idx = 1 + for unrefined_panel_idx in 1:n_unrefined_panels + le_mid_unref = (wing.sections[unrefined_panel_idx].LE_point + + wing.sections[unrefined_panel_idx+1].LE_point) / 2 + te_mid_unref = (wing.sections[unrefined_panel_idx].TE_point + + wing.sections[unrefined_panel_idx+1].TE_point) / 2 + unrefined_center = (le_mid_unref + te_mid_unref) / 2 + + dist = norm(refined_center - unrefined_center) + if dist < min_dist + min_dist = dist + closest_idx = unrefined_panel_idx + end + end + + # Verify mapping is correct + @test wing.refined_panel_mapping[refined_panel_idx] == closest_idx + end + end + + @testset "COSINE distribution" begin + n_panels = 30 + span = 20.0 + + wing = Wing(n_panels; spanwise_distribution=COSINE, n_groups=3, grouping_method=REFINE) + # 4 sections = 3 unrefined panels + add_section!(wing, [0.0, span/2, 0.0], [1.0, span/2, 0.0], INVISCID) + add_section!(wing, [0.0, span/6, 0.0], [1.0, span/6, 0.0], INVISCID) + add_section!(wing, [0.0, -span/6, 0.0], [1.0, -span/6, 0.0], INVISCID) + add_section!(wing, [0.0, -span/2, 0.0], [1.0, -span/2, 0.0], INVISCID) + + refine_aerodynamic_mesh!(wing) + + @test length(wing.refined_panel_mapping) == n_panels + + # Verify each panel is mapped to its closest unrefined panel + n_unrefined_panels = length(wing.sections) - 1 + for refined_panel_idx in 1:n_panels + # Calculate refined panel center + le_mid = (wing.refined_sections[refined_panel_idx].LE_point + + wing.refined_sections[refined_panel_idx+1].LE_point) / 2 + te_mid = (wing.refined_sections[refined_panel_idx].TE_point + + wing.refined_sections[refined_panel_idx+1].TE_point) / 2 + refined_center = (le_mid + te_mid) / 2 + + # Find closest unrefined panel manually + min_dist = Inf + closest_idx = 1 + for unrefined_panel_idx in 1:n_unrefined_panels + le_mid_unref = (wing.sections[unrefined_panel_idx].LE_point + + wing.sections[unrefined_panel_idx+1].LE_point) / 2 + te_mid_unref = (wing.sections[unrefined_panel_idx].TE_point + + wing.sections[unrefined_panel_idx+1].TE_point) / 2 + unrefined_center = (le_mid_unref + te_mid_unref) / 2 + + dist = norm(refined_center - unrefined_center) + if dist < min_dist + min_dist = dist + closest_idx = unrefined_panel_idx + end + end + + # Verify mapping is correct + @test wing.refined_panel_mapping[refined_panel_idx] == closest_idx + end + end + + @testset "SPLIT_PROVIDED distribution" begin + n_panels = 12 + + wing = Wing(n_panels; spanwise_distribution=SPLIT_PROVIDED, n_groups=3, grouping_method=REFINE) + # 4 sections = 3 unrefined panels + add_section!(wing, [0.0, 6.0, 0.0], [1.0, 6.0, 0.0], INVISCID) + add_section!(wing, [0.0, 2.0, 0.0], [1.0, 2.0, 0.0], INVISCID) + add_section!(wing, [0.0, -2.0, 0.0], [1.0, -2.0, 0.0], INVISCID) + add_section!(wing, [0.0, -6.0, 0.0], [1.0, -6.0, 0.0], INVISCID) + + refine_aerodynamic_mesh!(wing) + + @test length(wing.refined_panel_mapping) == n_panels + + # Verify each panel is mapped to its closest unrefined panel + n_unrefined_panels = length(wing.sections) - 1 + for refined_panel_idx in 1:n_panels + # Calculate refined panel center + le_mid = (wing.refined_sections[refined_panel_idx].LE_point + + wing.refined_sections[refined_panel_idx+1].LE_point) / 2 + te_mid = (wing.refined_sections[refined_panel_idx].TE_point + + wing.refined_sections[refined_panel_idx+1].TE_point) / 2 + refined_center = (le_mid + te_mid) / 2 + + # Find closest unrefined panel manually + min_dist = Inf + closest_idx = 1 + for unrefined_panel_idx in 1:n_unrefined_panels + le_mid_unref = (wing.sections[unrefined_panel_idx].LE_point + + wing.sections[unrefined_panel_idx+1].LE_point) / 2 + te_mid_unref = (wing.sections[unrefined_panel_idx].TE_point + + wing.sections[unrefined_panel_idx+1].TE_point) / 2 + unrefined_center = (le_mid_unref + te_mid_unref) / 2 + + dist = norm(refined_center - unrefined_center) + if dist < min_dist + min_dist = dist + closest_idx = unrefined_panel_idx + end + end + + # Verify mapping is correct + @test wing.refined_panel_mapping[refined_panel_idx] == closest_idx + end + end + + @testset "Validation: n_groups must equal unrefined panels" begin + wing = Wing(20; spanwise_distribution=LINEAR, n_groups=5, grouping_method=REFINE) + add_section!(wing, [0.0, 5.0, 0.0], [1.0, 5.0, 0.0], INVISCID) + add_section!(wing, [0.0, 0.0, 0.0], [1.0, 0.0, 0.0], INVISCID) + add_section!(wing, [0.0, -5.0, 0.0], [1.0, -5.0, 0.0], INVISCID) + + # Should throw error: 5 groups but only 2 unrefined panels + @test_throws ArgumentError refine_aerodynamic_mesh!(wing) + end + end end \ No newline at end of file From 35356430c0ef65814501f2fba2be71ea1a43a595 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Wed, 29 Oct 2025 15:57:35 +0100 Subject: [PATCH 07/86] Working tests with aqua --- Project.toml | 2 ++ test/Project.toml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/Project.toml b/Project.toml index 29000957..7609394f 100644 --- a/Project.toml +++ b/Project.toml @@ -39,6 +39,7 @@ VortexStepMethodMakieExt = "Makie" [compat] Colors = "0.13" +ControlPlots = "0.2.5" DefaultApplication = "1" DelimitedFiles = "1" DifferentiationInterface = "0.7.4" @@ -47,6 +48,7 @@ Interpolations = "0.15, 0.16" LaTeXStrings = "1" LinearAlgebra = "1" Logging = "1" +Makie = "0.24.6" Measures = "0.3" NonlinearSolve = "4.8.0" Parameters = "0.12" diff --git a/test/Project.toml b/test/Project.toml index 32eda93f..9ede8c7a 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -22,9 +22,11 @@ CSV = "0.10" ControlPlots = "0.2.5" DataFrames = "1.7" Documenter = "1.8" +Interpolations = "0.15, 0.16" LinearAlgebra = "1" Logging = "1" Random = "1.10.0" +Serialization = "1" StaticArrays = "1" Statistics = "1" Test = "1" From 2b0301504a3ac6a2c14054df13f28bc6ee5713e8 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sat, 1 Nov 2025 23:31:49 +0100 Subject: [PATCH 08/86] Don't deform tuple --- examples/Project.toml | 3 + src/wing_geometry.jl | 8 +- test/yaml_geometry/test_yaml_geometry.jl | 1 + .../test_yaml_wing_deformation.jl | 175 ++++++++++++++++++ 4 files changed, 184 insertions(+), 3 deletions(-) create mode 100644 examples/Project.toml create mode 100644 test/yaml_geometry/test_yaml_wing_deformation.jl diff --git a/examples/Project.toml b/examples/Project.toml new file mode 100644 index 00000000..24966cd6 --- /dev/null +++ b/examples/Project.toml @@ -0,0 +1,3 @@ +[deps] +ControlPlots = "23c2ee80-7a9e-4350-b264-8e670f12517c" +VortexStepMethod = "ed3cd733-9f0f-46a9-93e0-89b8d4998dd9" diff --git a/src/wing_geometry.jl b/src/wing_geometry.jl index 02f7a308..4f00d2d4 100644 --- a/src/wing_geometry.jl +++ b/src/wing_geometry.jl @@ -44,10 +44,12 @@ function reinit!(section::Section, LE_point, TE_point, aero_model=nothing, aero_ section.TE_point .= TE_point (!isnothing(aero_model)) && (section.aero_model = aero_model) if !isnothing(aero_data) - if !isnothing(section.aero_data) - section.aero_data .= aero_data - else + # NTuple is immutable, so we must assign directly + # For mutable types (Vector, Matrix), we can broadcast for efficiency + if aero_data isa NTuple || isnothing(section.aero_data) section.aero_data = aero_data + else + section.aero_data .= aero_data end end nothing diff --git a/test/yaml_geometry/test_yaml_geometry.jl b/test/yaml_geometry/test_yaml_geometry.jl index 12daa54f..58924a91 100644 --- a/test/yaml_geometry/test_yaml_geometry.jl +++ b/test/yaml_geometry/test_yaml_geometry.jl @@ -4,4 +4,5 @@ using Test # Include specific test files for better organization include("test_load_polar_data.jl") include("test_wing_constructor.jl") + include("test_yaml_wing_deformation.jl") end diff --git a/test/yaml_geometry/test_yaml_wing_deformation.jl b/test/yaml_geometry/test_yaml_wing_deformation.jl new file mode 100644 index 00000000..da931177 --- /dev/null +++ b/test/yaml_geometry/test_yaml_wing_deformation.jl @@ -0,0 +1,175 @@ +using VortexStepMethod +using LinearAlgebra +using Test + +@testset "YAML Wing Deformation Tests" begin + @testset "Simple Wing Deformation" begin + # Load existing simple_wing.yaml + simple_wing_file = test_data_path("yaml_geometry", "simple_wing.yaml") + wing = Wing(simple_wing_file; n_panels=4, n_groups=2) + body_aero = BodyAerodynamics([wing]) + + # Store original TE point for comparison + i = length(body_aero.panels) ÷ 2 + original_te_point = copy(body_aero.panels[i].TE_point_1) + original_le_point = copy(body_aero.panels[i].LE_point_1) + + # Apply deformation with non-zero angles + theta_dist = fill(deg2rad(30.0), wing.n_panels) # 30 degrees twist + delta_dist = fill(deg2rad(5.0), wing.n_panels) # 5 degrees trailing edge deflection + + VortexStepMethod.deform!(wing, theta_dist, delta_dist) + VortexStepMethod.reinit!(body_aero) + + # Check if TE point changed after deformation + deformed_te_point = copy(body_aero.panels[i].TE_point_1) + deformed_le_point = copy(body_aero.panels[i].LE_point_1) + + # TE point should change significantly due to twist and deflection + @test !isapprox(original_te_point, deformed_te_point, atol=1e-2) + @test deformed_te_point[3] < original_te_point[3] # TE should move down with positive twist + + # LE point should also change due to twist + @test !isapprox(original_le_point, deformed_le_point, atol=1e-2) + + # Check delta is set correctly + @test body_aero.panels[i].delta ≈ deg2rad(5.0) + + # Reset deformation with zero angles + zero_theta_dist = zeros(wing.n_panels) + zero_delta_dist = zeros(wing.n_panels) + + VortexStepMethod.deform!(wing, zero_theta_dist, zero_delta_dist) + VortexStepMethod.reinit!(body_aero) + + # Check if TE point returned to original position + reset_te_point = copy(body_aero.panels[i].TE_point_1) + reset_le_point = copy(body_aero.panels[i].LE_point_1) + @test original_te_point ≈ reset_te_point atol=1e-4 + @test original_le_point ≈ reset_le_point atol=1e-4 + @test body_aero.panels[i].delta ≈ 0.0 atol=1e-4 + end + + @testset "Complex Wing Deformation" begin + # Load existing complex_wing.yaml with multiple sections + complex_wing_file = test_data_path("yaml_geometry", "complex_wing.yaml") + wing = Wing(complex_wing_file; n_panels=12, n_groups=3) + 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 + + # Apply spanwise-varying deformation + theta_dist = [deg2rad(10.0 * i / wing.n_panels) for i in 1:wing.n_panels] # Linear twist distribution + delta_dist = [deg2rad(-5.0 + 10.0 * i / wing.n_panels) for i in 1:wing.n_panels] # Varying deflection + + VortexStepMethod.deform!(wing, theta_dist, delta_dist) + VortexStepMethod.reinit!(body_aero) + + # Check that different panels have different deformations + for (idx, i) in enumerate(test_indices) + deformed_te = body_aero.panels[i].TE_point_1 + deformed_le = body_aero.panels[i].LE_point_1 + + # Points should have changed + @test !isapprox(original_points[idx].TE, deformed_te, atol=1e-2) + @test !isapprox(original_points[idx].LE, deformed_le, atol=1e-2) + end + + # Check that the deformation is applied correctly + # First panel should have smaller theta, last panel should have larger theta + @test body_aero.panels[1].delta < body_aero.panels[end].delta + + # Reset and verify + VortexStepMethod.deform!(wing, zeros(wing.n_panels), zeros(wing.n_panels)) + VortexStepMethod.reinit!(body_aero) + + for (idx, i) in enumerate(test_indices) + reset_te = body_aero.panels[i].TE_point_1 + reset_le = body_aero.panels[i].LE_point_1 + @test original_points[idx].TE ≈ reset_te atol=1e-4 + @test original_points[idx].LE ≈ reset_le atol=1e-4 + @test body_aero.panels[i].delta ≈ 0.0 atol=1e-4 + end + end + + @testset "Multiple Reinit Calls with NTuple aero_data" begin + # This test specifically checks the NTuple handling fix + simple_wing_file = test_data_path("yaml_geometry", "simple_wing.yaml") + wing = Wing(simple_wing_file; n_panels=4, n_groups=2) + + # Verify that sections have NTuple aero_data (for wings with simple polars) + # or other valid AeroData types + @test wing.sections[1].aero_data !== nothing + + # Perform multiple reinit! calls to ensure NTuple handling works + for _ in 1:5 + VortexStepMethod.reinit!(wing) + end + + # Wing should still be valid after multiple reinits + @test wing.sections[1].aero_data !== nothing + @test length(wing.sections) == 2 + end + + @testset "Deformation with BodyAerodynamics Reinit" begin + # Test that reinit! on BodyAerodynamics properly handles deformed wings + simple_wing_file = test_data_path("yaml_geometry", "simple_wing.yaml") + wing = Wing(simple_wing_file; n_panels=4, n_groups=2) + body_aero = BodyAerodynamics([wing]) + + # Apply deformation + theta_dist = fill(deg2rad(15.0), wing.n_panels) + delta_dist = fill(deg2rad(3.0), wing.n_panels) + VortexStepMethod.deform!(wing, theta_dist, delta_dist) + + # Store state after deformation + i = length(body_aero.panels) ÷ 2 + + # Multiple reinit calls should work without errors + for _ in 1:3 + VortexStepMethod.reinit!(body_aero; + va=zeros(3), + omega=zeros(3), + init_aero=true + ) + end + + # Panel should maintain deformation + @test body_aero.panels[i].delta ≈ deg2rad(3.0) atol=1e-6 + end + + @testset "Edge Cases" begin + simple_wing_file = test_data_path("yaml_geometry", "simple_wing.yaml") + wing = Wing(simple_wing_file; n_panels=2, n_groups=1) + body_aero = BodyAerodynamics([wing]) + + # Test zero deformation + VortexStepMethod.deform!(wing, zeros(wing.n_panels), zeros(wing.n_panels)) + VortexStepMethod.reinit!(body_aero) + @test all(p.delta ≈ 0.0 for p in body_aero.panels) + + # Test large deformation angles + theta_dist = fill(deg2rad(60.0), wing.n_panels) + delta_dist = fill(deg2rad(30.0), wing.n_panels) + + # Should not error even with large angles + VortexStepMethod.deform!(wing, theta_dist, delta_dist) + VortexStepMethod.reinit!(body_aero) + @test all(p.delta ≈ deg2rad(30.0) for p in body_aero.panels) + + # Test negative angles + theta_dist = fill(deg2rad(-20.0), wing.n_panels) + delta_dist = fill(deg2rad(-10.0), wing.n_panels) + VortexStepMethod.deform!(wing, theta_dist, delta_dist) + VortexStepMethod.reinit!(body_aero) + @test all(p.delta ≈ deg2rad(-10.0) for p in body_aero.panels) + end +end From 4ca52ac9ead629999d2260ce12f639ba9fd576db Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Thu, 6 Nov 2025 15:20:03 +0100 Subject: [PATCH 09/86] Option to not use data prefix --- src/settings.jl | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/settings.jl b/src/settings.jl index fe538ed9..3448802d 100644 --- a/src/settings.jl +++ b/src/settings.jl @@ -40,9 +40,13 @@ end solver_settings::SolverSettings = SolverSettings() end -function VSMSettings(filename) +function VSMSettings(filename; data_prefix=true) # Uwe's suggested 3-line approach using StructMapping.jl (adapted) - data = YAML.load_file(joinpath("data", filename)) + if data_prefix + data = YAML.load_file(joinpath("data", filename)) + else + data = YAML.load_file(filename) + end # Use StructMapping for basic structure conversion # But handle special fields manually due to enum conversion needs @@ -110,4 +114,4 @@ function Base.show(io::IO, vsm_settings::VSMSettings) print(io, replace(repr(wing), "\n" => "\n ")) end print(io, replace(repr(vsm_settings.solver_settings), "\n" => "\n ")) -end \ No newline at end of file +end From 128f720fae4b8584642a08577a36cb58d6bf103b Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Fri, 7 Nov 2025 11:11:58 +0100 Subject: [PATCH 10/86] Add obj set --- src/settings.jl | 12 +++- src/yaml_geometry.jl | 71 ++++++++++++++++--- test/settings/test_settings.jl | 2 +- .../test_yaml_wing_deformation.jl | 12 ++-- 4 files changed, 80 insertions(+), 17 deletions(-) diff --git a/src/settings.jl b/src/settings.jl index 3448802d..ad3fb75f 100644 --- a/src/settings.jl +++ b/src/settings.jl @@ -8,8 +8,10 @@ end @with_kw mutable struct WingSettings name::String = "main_wing" geometry_file::String = "" # path to wing geometry YAML file + obj_file::String = "" # path to .obj geometry file + dat_file::String = "" # path to .dat airfoil file n_panels::Int64 = 40 - n_groups::Int64 = 40 + n_groups::Int64 = 40 spanwise_panel_distribution::PanelDistribution = LINEAR spanwise_direction::MVec3 = [0.0, 1.0, 0.0] remove_nan = true @@ -68,12 +70,18 @@ function VSMSettings(filename; data_prefix=true) if haskey(wing_data, "geometry_file") wing.geometry_file = wing_data["geometry_file"] end + if haskey(wing_data, "obj_file") + wing.obj_file = wing_data["obj_file"] + end + if haskey(wing_data, "dat_file") + wing.dat_file = wing_data["dat_file"] + end wing.n_panels = wing_data["n_panels"] wing.n_groups = wing_data["n_groups"] wing.spanwise_panel_distribution = eval(Symbol(wing_data["spanwise_panel_distribution"])) wing.spanwise_direction = MVec3(wing_data["spanwise_direction"]) wing.remove_nan = wing_data["remove_nan"] - + push!(vsm_settings.wings, wing) n_panels += wing.n_panels n_groups += wing.n_groups diff --git a/src/yaml_geometry.jl b/src/yaml_geometry.jl index 3ba618f5..8279d525 100644 --- a/src/yaml_geometry.jl +++ b/src/yaml_geometry.jl @@ -275,9 +275,13 @@ end Create a wing model from VSM settings configuration. -This constructor is a convenience wrapper that extracts wing configuration -from VSMSettings and creates a Wing using the YAML geometry file path and -parameters specified in the settings. +This constructor is a convenience wrapper that extracts wing configuration +from VSMSettings and creates a Wing using either: +- YAML geometry file (geometry_file field), or +- OBJ + DAT files (obj_file and dat_file fields) + +The constructor automatically determines which path to use based on which +fields are populated in the settings. # Arguments - `settings`: VSMSettings object containing wing configuration @@ -287,15 +291,64 @@ A fully initialized `Wing` instance ready for aerodynamic simulation. # Example ```julia -# Load settings and create wing in one step +# Using YAML geometry settings = VSMSettings("path/to/vsm_settings.yaml") wing = Wing(settings) + +# Settings can specify either: +# - geometry_file: "path/to/wing.yaml" # YAML-based +# - obj_file + dat_file # OBJ-based ``` """ function Wing(settings::VSMSettings) - Wing(settings.wings[1].geometry_file; - n_panels=settings.wings[1].n_panels, - n_groups=settings.wings[1].n_groups, - spanwise_distribution=settings.wings[1].spanwise_panel_distribution - ) + wing_settings = settings.wings[1] + + # Check which geometry format to use + has_yaml = !isempty(wing_settings.geometry_file) + has_obj = !isempty(wing_settings.obj_file) + has_dat = !isempty(wing_settings.dat_file) + + if has_yaml && (has_obj || has_dat) + throw(ArgumentError( + "Cannot specify both geometry_file and obj_file/dat_file" + )) + end + + if has_obj && !has_dat + throw(ArgumentError( + "obj_file requires dat_file to be specified" + )) + end + + if has_dat && !has_obj + throw(ArgumentError( + "dat_file requires obj_file to be specified" + )) + end + + if has_yaml + # Use YAML geometry constructor + Wing(wing_settings.geometry_file; + n_panels=wing_settings.n_panels, + n_groups=wing_settings.n_groups, + spanwise_distribution=wing_settings.spanwise_panel_distribution, + remove_nan=wing_settings.remove_nan + ) + elseif has_obj && has_dat + # Use ObjWing constructor + ObjWing( + wing_settings.obj_file, + wing_settings.dat_file; + n_panels=wing_settings.n_panels, + n_groups=wing_settings.n_groups, + spanwise_distribution=wing_settings.spanwise_panel_distribution, + spanwise_direction=wing_settings.spanwise_direction, + remove_nan=wing_settings.remove_nan + ) + else + throw(ArgumentError( + "WingSettings must specify either geometry_file or " * + "both obj_file and dat_file" + )) + end end diff --git a/test/settings/test_settings.jl b/test/settings/test_settings.jl index c7412894..80126bcf 100644 --- a/test/settings/test_settings.jl +++ b/test/settings/test_settings.jl @@ -16,6 +16,6 @@ using Test @test vss.wings isa Vector{WingSettings} @test length(vss.wings) == 2 io = IOBuffer(repr(vss)) - @test countlines(io) == 40 # Updated to match new output format + @test countlines(io) == 44 # Updated to match new output format end nothing diff --git a/test/yaml_geometry/test_yaml_wing_deformation.jl b/test/yaml_geometry/test_yaml_wing_deformation.jl index da931177..2631f2cc 100644 --- a/test/yaml_geometry/test_yaml_wing_deformation.jl +++ b/test/yaml_geometry/test_yaml_wing_deformation.jl @@ -29,8 +29,8 @@ using Test @test !isapprox(original_te_point, deformed_te_point, atol=1e-2) @test deformed_te_point[3] < original_te_point[3] # TE should move down with positive twist - # LE point should also change due to twist - @test !isapprox(original_le_point, deformed_le_point, atol=1e-2) + # LE point stays fixed (deform! rotates TE around LE) + @test isapprox(original_le_point, deformed_le_point, atol=1e-4) # Check delta is set correctly @test body_aero.panels[i].delta ≈ deg2rad(5.0) @@ -78,9 +78,10 @@ using Test deformed_te = body_aero.panels[i].TE_point_1 deformed_le = body_aero.panels[i].LE_point_1 - # Points should have changed + # TE points should have changed due to deformation @test !isapprox(original_points[idx].TE, deformed_te, atol=1e-2) - @test !isapprox(original_points[idx].LE, deformed_le, atol=1e-2) + # LE points stay fixed (deform! rotates TE around LE) + @test isapprox(original_points[idx].LE, deformed_le, atol=1e-4) end # Check that the deformation is applied correctly @@ -116,7 +117,8 @@ using Test # Wing should still be valid after multiple reinits @test wing.sections[1].aero_data !== nothing - @test length(wing.sections) == 2 + # Note: For deformation support, wing.sections now points to refined_sections + @test length(wing.sections) == wing.n_panels + 1 end @testset "Deformation with BodyAerodynamics Reinit" begin From 7a7e2038095fe8daeb4ca8d11dbaf0e03b61a19a Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Fri, 7 Nov 2025 13:09:45 +0100 Subject: [PATCH 11/86] Old tests not failing --- src/wing_geometry.jl | 32 +++++++++++++++++-- .../test_yaml_wing_deformation.jl | 11 +++++-- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/wing_geometry.jl b/src/wing_geometry.jl index a1efc422..4ce34568 100644 --- a/src/wing_geometry.jl +++ b/src/wing_geometry.jl @@ -450,7 +450,7 @@ function deform!(wing::Wing) local_y .= normalize(section1.LE_point - section2.LE_point) chord .= section1.TE_point .- section1.LE_point normal .= chord × local_y - @. wing.sections[i].TE_point = section1.LE_point + cos(wing.theta_dist[i]) * chord - sin(wing.theta_dist[i]) * normal + @. wing.refined_sections[i].TE_point = section1.LE_point + cos(wing.theta_dist[i]) * chord - sin(wing.theta_dist[i]) * normal end return nothing end @@ -528,6 +528,28 @@ function flip_created_coord_in_pairs_if_needed!(coord::Matrix{Float64}) end +""" + update_non_deformed_sections!(wing::AbstractWing) + +Create non_deformed_sections to match refined_sections. +This enables deformation support for all wings (YAML and OBJ). +Should be called after refined_sections are populated for the FIRST time only. +Once populated, non_deformed_sections serves as the undeformed reference geometry. +""" +function update_non_deformed_sections!(wing::AbstractWing) + n_sections = wing.n_panels + 1 + + # Only populate non_deformed_sections if it's empty (initial setup) + # Once populated, it serves as the undeformed reference and should not be overwritten + if isempty(wing.non_deformed_sections) + wing.non_deformed_sections = [Section() for _ in 1:n_sections] + for i in 1:n_sections + reinit!(wing.non_deformed_sections[i], wing.refined_sections[i]) + end + end + return nothing +end + """ refine_aerodynamic_mesh!(wing::AbstractWing) @@ -542,6 +564,7 @@ function refine_aerodynamic_mesh!(wing::AbstractWing) if length(wing.refined_sections) == 0 if wing.spanwise_distribution == UNCHANGED || length(wing.sections) == n_sections wing.refined_sections = wing.sections + update_non_deformed_sections!(wing) return nothing else wing.refined_sections = Section[Section() for _ in 1:wing.n_panels+1] @@ -573,6 +596,7 @@ function refine_aerodynamic_mesh!(wing::AbstractWing) reinit!(wing.refined_sections[i], wing.sections[i]) end compute_refined_panel_mapping!(wing) + update_non_deformed_sections!(wing) return nothing end @@ -583,6 +607,7 @@ function refine_aerodynamic_mesh!(wing::AbstractWing) reinit!(wing.refined_sections[1], LE[1,:], TE[1,:], aero_model[1], aero_data[1]) reinit!(wing.refined_sections[2], LE[end,:], TE[end,:], aero_model[end], aero_data[end]) compute_refined_panel_mapping!(wing) + update_non_deformed_sections!(wing) return nothing end @@ -619,6 +644,9 @@ function refine_aerodynamic_mesh!(wing::AbstractWing) end end + # Create/update non_deformed_sections to match refined_sections + update_non_deformed_sections!(wing) + return nothing end @@ -1116,4 +1144,4 @@ function Base.getproperty(w::AbstractWing, s::Symbol) else return getfield(w, s) end -end \ No newline at end of file +end diff --git a/test/yaml_geometry/test_yaml_wing_deformation.jl b/test/yaml_geometry/test_yaml_wing_deformation.jl index 2631f2cc..75d64642 100644 --- a/test/yaml_geometry/test_yaml_wing_deformation.jl +++ b/test/yaml_geometry/test_yaml_wing_deformation.jl @@ -2,6 +2,12 @@ using VortexStepMethod using LinearAlgebra using Test +# Load TestSupport if not already loaded (for standalone execution) +if !@isdefined(TestSupport) + include(joinpath(@__DIR__, "..", "TestSupport.jl")) + using .TestSupport +end + @testset "YAML Wing Deformation Tests" begin @testset "Simple Wing Deformation" begin # Load existing simple_wing.yaml @@ -117,8 +123,9 @@ using Test # Wing should still be valid after multiple reinits @test wing.sections[1].aero_data !== nothing - # Note: For deformation support, wing.sections now points to refined_sections - @test length(wing.sections) == wing.n_panels + 1 + # Verify refined_sections and non_deformed_sections are properly populated + @test length(wing.refined_sections) == wing.n_panels + 1 + @test length(wing.non_deformed_sections) == wing.n_panels + 1 end @testset "Deformation with BodyAerodynamics Reinit" begin From 2ef5c3ed581cbeec08ca1e614c71d0386e61e1ba Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Fri, 7 Nov 2025 15:03:13 +0100 Subject: [PATCH 12/86] Passing tests --- src/body_aerodynamics.jl | 9 ++++++--- src/wing_geometry.jl | 16 ++++++++++++++-- .../test_yaml_wing_deformation.jl | 18 ++++++++++-------- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/src/body_aerodynamics.jl b/src/body_aerodynamics.jl index 9e09f54c..103745dc 100644 --- a/src/body_aerodynamics.jl +++ b/src/body_aerodynamics.jl @@ -114,7 +114,7 @@ function Base.setproperty!(obj::BodyAerodynamics, sym::Symbol, val) end """ - reinit!(body_aero::BodyAerodynamics; init_aero, va, omega) + reinit!(body_aero::BodyAerodynamics; init_aero, va, omega, refine_mesh) Initialize a BodyAerodynamics struct in-place by setting up panels and coefficients. @@ -125,6 +125,8 @@ Initialize a BodyAerodynamics struct in-place by setting up panels and coefficie - `init_aero::Bool`: Wether to initialize the aero data or not - `va=[15.0, 0.0, 0.0]`: Apparent wind vector - `omega=zeros(3)`: Turn rate in kite body frame x y and z +- `refine_mesh=true`: Whether to refine wing meshes. Set to `false` after + `deform!()` to preserve deformed geometry. # Returns nothing @@ -132,12 +134,13 @@ nothing function reinit!(body_aero::BodyAerodynamics; init_aero=true, va=[15.0, 0.0, 0.0], - omega=zeros(MVec3) + omega=zeros(MVec3), + refine_mesh=true ) idx = 1 vec = @MVector zeros(3) for wing in body_aero.wings - reinit!(wing) + reinit!(wing; refine_mesh=refine_mesh) panel_props = wing.panel_props # Create panels diff --git a/src/wing_geometry.jl b/src/wing_geometry.jl index 4ce34568..79554cb4 100644 --- a/src/wing_geometry.jl +++ b/src/wing_geometry.jl @@ -301,8 +301,20 @@ function Wing(n_panels::Int; ) end -function reinit!(wing::AbstractWing) - refine_aerodynamic_mesh!(wing) +""" + reinit!(wing::AbstractWing; refine_mesh=true) + +Reinitialize wing geometry and panel properties. + +# Keyword Arguments +- `refine_mesh::Bool=true`: Whether to refine the mesh. Set to `false` after + `deform!()` to preserve deformed geometry while updating panel properties. +""" +function reinit!(wing::AbstractWing; refine_mesh=true) + # Refine mesh unless explicitly disabled (e.g., to preserve deformation) + if refine_mesh + refine_aerodynamic_mesh!(wing) + end # Calculate panel properties update_panel_properties!( diff --git a/test/yaml_geometry/test_yaml_wing_deformation.jl b/test/yaml_geometry/test_yaml_wing_deformation.jl index 75d64642..580e3dc9 100644 --- a/test/yaml_geometry/test_yaml_wing_deformation.jl +++ b/test/yaml_geometry/test_yaml_wing_deformation.jl @@ -25,7 +25,7 @@ end delta_dist = fill(deg2rad(5.0), wing.n_panels) # 5 degrees trailing edge deflection VortexStepMethod.deform!(wing, theta_dist, delta_dist) - VortexStepMethod.reinit!(body_aero) + VortexStepMethod.reinit!(body_aero; refine_mesh=false) # Check if TE point changed after deformation deformed_te_point = copy(body_aero.panels[i].TE_point_1) @@ -46,7 +46,7 @@ end zero_delta_dist = zeros(wing.n_panels) VortexStepMethod.deform!(wing, zero_theta_dist, zero_delta_dist) - VortexStepMethod.reinit!(body_aero) + VortexStepMethod.reinit!(body_aero; refine_mesh=false) # Check if TE point returned to original position reset_te_point = copy(body_aero.panels[i].TE_point_1) @@ -77,7 +77,7 @@ end delta_dist = [deg2rad(-5.0 + 10.0 * i / wing.n_panels) for i in 1:wing.n_panels] # Varying deflection VortexStepMethod.deform!(wing, theta_dist, delta_dist) - VortexStepMethod.reinit!(body_aero) + VortexStepMethod.reinit!(body_aero; refine_mesh=false) # Check that different panels have different deformations for (idx, i) in enumerate(test_indices) @@ -96,7 +96,7 @@ end # Reset and verify VortexStepMethod.deform!(wing, zeros(wing.n_panels), zeros(wing.n_panels)) - VortexStepMethod.reinit!(body_aero) + VortexStepMethod.reinit!(body_aero; refine_mesh=false) for (idx, i) in enumerate(test_indices) reset_te = body_aero.panels[i].TE_point_1 @@ -138,6 +138,7 @@ end theta_dist = fill(deg2rad(15.0), wing.n_panels) delta_dist = fill(deg2rad(3.0), wing.n_panels) VortexStepMethod.deform!(wing, theta_dist, delta_dist) + VortexStepMethod.reinit!(body_aero; refine_mesh=false) # Store state after deformation i = length(body_aero.panels) ÷ 2 @@ -147,7 +148,8 @@ end VortexStepMethod.reinit!(body_aero; va=zeros(3), omega=zeros(3), - init_aero=true + init_aero=true, + refine_mesh=false ) end @@ -162,7 +164,7 @@ end # Test zero deformation VortexStepMethod.deform!(wing, zeros(wing.n_panels), zeros(wing.n_panels)) - VortexStepMethod.reinit!(body_aero) + VortexStepMethod.reinit!(body_aero; refine_mesh=false) @test all(p.delta ≈ 0.0 for p in body_aero.panels) # Test large deformation angles @@ -171,14 +173,14 @@ end # Should not error even with large angles VortexStepMethod.deform!(wing, theta_dist, delta_dist) - VortexStepMethod.reinit!(body_aero) + VortexStepMethod.reinit!(body_aero; refine_mesh=false) @test all(p.delta ≈ deg2rad(30.0) for p in body_aero.panels) # Test negative angles theta_dist = fill(deg2rad(-20.0), wing.n_panels) delta_dist = fill(deg2rad(-10.0), wing.n_panels) VortexStepMethod.deform!(wing, theta_dist, delta_dist) - VortexStepMethod.reinit!(body_aero) + VortexStepMethod.reinit!(body_aero; refine_mesh=false) @test all(p.delta ≈ deg2rad(-10.0) for p in body_aero.panels) end end From dad4e72a9ae82d6456b077379b9f0d9bc9a32214 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Fri, 7 Nov 2025 15:50:13 +0100 Subject: [PATCH 13/86] Add cl cd cm group array --- src/solver.jl | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/src/solver.jl b/src/solver.jl index 7f4daec3..742d921b 100644 --- a/src/solver.jl +++ b/src/solver.jl @@ -51,6 +51,9 @@ Struct for storing the solution of the [solve!](@ref) function. Must contain all moment_coeff_dist::MVector{P, Float64} = zeros(P) group_moment_dist::MVector{G, Float64} = zeros(G) group_moment_coeff_dist::MVector{G, Float64} = zeros(G) + cl_group_array::MVector{G, Float64} = zeros(G) + cd_group_array::MVector{G, Float64} = zeros(G) + cm_group_array::MVector{G, Float64} = zeros(G) solver_status::SolverStatus = FAILURE end @@ -296,8 +299,14 @@ function solve!(solver::Solver, body_aero::BodyAerodynamics, gamma_distribution= if length(solver.sol.group_moment_dist) > 0 group_moment_dist = solver.sol.group_moment_dist group_moment_coeff_dist = solver.sol.group_moment_coeff_dist + cl_group_array = solver.sol.cl_group_array + cd_group_array = solver.sol.cd_group_array + cm_group_array = solver.sol.cm_group_array group_moment_dist .= 0.0 group_moment_coeff_dist .= 0.0 + cl_group_array .= 0.0 + cd_group_array .= 0.0 + cm_group_array .= 0.0 panel_idx = 1 group_idx = 1 for wing in body_aero.wings @@ -306,21 +315,46 @@ function solve!(solver::Solver, body_aero::BodyAerodynamics, gamma_distribution= # Original method: divide panels into equally-sized sequential groups panels_per_group = wing.n_panels ÷ wing.n_groups for _ in 1:wing.n_groups + panel_count = 0 for _ in 1:panels_per_group group_moment_dist[group_idx] += moment_dist[panel_idx] group_moment_coeff_dist[group_idx] += moment_coeff_dist[panel_idx] + cl_group_array[group_idx] += solver.sol.cl_array[panel_idx] + cd_group_array[group_idx] += solver.sol.cd_array[panel_idx] + cm_group_array[group_idx] += solver.sol.cm_array[panel_idx] panel_idx += 1 + panel_count += 1 end + # Average the coefficients over panels in the group + cl_group_array[group_idx] /= panel_count + cd_group_array[group_idx] /= panel_count + cm_group_array[group_idx] /= panel_count group_idx += 1 end elseif wing.grouping_method == REFINE # REFINE method: group refined panels by their original unrefined section + # First pass: accumulate values + group_panel_counts = zeros(Int, wing.n_groups) for local_panel_idx in 1:wing.n_panels original_section_idx = wing.refined_panel_mapping[local_panel_idx] - group_moment_dist[group_idx + original_section_idx - 1] += moment_dist[panel_idx] - group_moment_coeff_dist[group_idx + original_section_idx - 1] += moment_coeff_dist[panel_idx] + target_group_idx = group_idx + original_section_idx - 1 + group_moment_dist[target_group_idx] += moment_dist[panel_idx] + group_moment_coeff_dist[target_group_idx] += moment_coeff_dist[panel_idx] + cl_group_array[target_group_idx] += solver.sol.cl_array[panel_idx] + cd_group_array[target_group_idx] += solver.sol.cd_array[panel_idx] + cm_group_array[target_group_idx] += solver.sol.cm_array[panel_idx] + group_panel_counts[original_section_idx] += 1 panel_idx += 1 end + # Second pass: average coefficients + for i in 1:wing.n_groups + target_group_idx = group_idx + i - 1 + if group_panel_counts[i] > 0 + cl_group_array[target_group_idx] /= group_panel_counts[i] + cd_group_array[target_group_idx] /= group_panel_counts[i] + cm_group_array[target_group_idx] /= group_panel_counts[i] + end + end group_idx += wing.n_groups end else From 1438b5572c521b247a564cfb70d8205f3b5b2c92 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Fri, 7 Nov 2025 16:23:17 +0100 Subject: [PATCH 14/86] Added tests and settings --- data/ram_air_kite/vsm_settings.yaml | 4 + src/settings.jl | 4 + test/runtests.jl | 1 + test/solver/test_group_coefficients.jl | 184 +++++++++++++++++++++++++ 4 files changed, 193 insertions(+) create mode 100644 test/solver/test_group_coefficients.jl diff --git a/data/ram_air_kite/vsm_settings.yaml b/data/ram_air_kite/vsm_settings.yaml index 5ae66dc9..8f726240 100644 --- a/data/ram_air_kite/vsm_settings.yaml +++ b/data/ram_air_kite/vsm_settings.yaml @@ -10,6 +10,9 @@ PanelDistribution: InitialGammaDistribution: ELLIPTIC: Elliptic distribution ZEROS: Constant distribution +PanelGroupingMethod: + EQUAL_SIZE: Divide panels into equally-sized sequential groups + REFINE: Group refined panels by their original unrefined section wings: - name: main_wing @@ -17,6 +20,7 @@ wings: n_groups: 40 spanwise_panel_distribution: LINEAR spanwise_direction: [0.0, 1.0, 0.0] + grouping_method: EQUAL_SIZE remove_nan: true solver_settings: n_panels: 40 diff --git a/src/settings.jl b/src/settings.jl index ad3fb75f..5916da52 100644 --- a/src/settings.jl +++ b/src/settings.jl @@ -14,6 +14,7 @@ end n_groups::Int64 = 40 spanwise_panel_distribution::PanelDistribution = LINEAR spanwise_direction::MVec3 = [0.0, 1.0, 0.0] + grouping_method::PanelGroupingMethod = EQUAL_SIZE remove_nan = true end @@ -80,6 +81,9 @@ function VSMSettings(filename; data_prefix=true) wing.n_groups = wing_data["n_groups"] wing.spanwise_panel_distribution = eval(Symbol(wing_data["spanwise_panel_distribution"])) wing.spanwise_direction = MVec3(wing_data["spanwise_direction"]) + if haskey(wing_data, "grouping_method") + wing.grouping_method = eval(Symbol(wing_data["grouping_method"])) + end wing.remove_nan = wing_data["remove_nan"] push!(vsm_settings.wings, wing) diff --git a/test/runtests.jl b/test/runtests.jl index 6c6f92cd..520eeab3 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -28,6 +28,7 @@ end::Bool include("ram_geometry/test_kite_geometry.jl") include("settings/test_settings.jl") include("solver/test_solver.jl") + include("solver/test_group_coefficients.jl") include("VortexStepMethod/test_VortexStepMethod.jl") include("wake/test_wake.jl") include("wing_geometry/test_wing_geometry.jl") diff --git a/test/solver/test_group_coefficients.jl b/test/solver/test_group_coefficients.jl new file mode 100644 index 00000000..7eae60ef --- /dev/null +++ b/test/solver/test_group_coefficients.jl @@ -0,0 +1,184 @@ +using VortexStepMethod +using LinearAlgebra +using Test + +# Load test support +include("../TestSupport.jl") +using .TestSupport + +@testset "Group Coefficient Arrays Tests" begin + @testset "Group coefficients with EQUAL_SIZE method" begin + # Create a simple wing with groups + n_panels = 20 + n_groups = 4 + + # Create a test wing settings file + settings_file = create_temp_wing_settings("solver", "solver_test_wing.yaml"; alpha=5.0, beta=0.0, wind_speed=10.0) + + try + # Modify settings to use specific panel/group configuration + settings = VSMSettings(settings_file) + settings.wings[1].n_panels = n_panels + settings.wings[1].n_groups = n_groups + settings.wings[1].grouping_method = EQUAL_SIZE + settings.solver_settings.n_panels = n_panels + settings.solver_settings.n_groups = n_groups + + # Create wing and solver + wing = Wing(settings) + body_aero = BodyAerodynamics([wing]) + solver = Solver(body_aero, settings) + + # Set conditions and solve + va = [10.0, 0.0, 0.0] + set_va!(body_aero, va) + sol = solve!(solver, body_aero) + + # Test 1: Group arrays exist and have correct size + @test length(sol.cl_group_array) == n_groups + @test length(sol.cd_group_array) == n_groups + @test length(sol.cm_group_array) == n_groups + + # Test 2: Group arrays are not all zeros (solver computed them) + @test !all(sol.cl_group_array .== 0.0) + @test !all(sol.cd_group_array .== 0.0) + + # Test 3: Verify group coefficients are averages of panel coefficients + panels_per_group = n_panels ÷ n_groups + for group_idx in 1:n_groups + panel_start = (group_idx - 1) * panels_per_group + 1 + panel_end = group_idx * panels_per_group + + # Calculate expected average from panel coefficients + expected_cl = sum(sol.cl_array[panel_start:panel_end]) / panels_per_group + expected_cd = sum(sol.cd_array[panel_start:panel_end]) / panels_per_group + expected_cm = sum(sol.cm_array[panel_start:panel_end]) / panels_per_group + + # Check if group coefficients match expected averages + # Handle NaN values that can occur in INVISCID models + if isnan(expected_cl) + @test isnan(sol.cl_group_array[group_idx]) + else + @test isapprox(sol.cl_group_array[group_idx], expected_cl, rtol=1e-10) + end + if isnan(expected_cd) + @test isnan(sol.cd_group_array[group_idx]) + else + @test isapprox(sol.cd_group_array[group_idx], expected_cd, rtol=1e-10) + end + if isnan(expected_cm) + @test isnan(sol.cm_group_array[group_idx]) + else + @test isapprox(sol.cm_group_array[group_idx], expected_cm, rtol=1e-10) + end + end + + # Test 4: Verify physical consistency (lift coefficients should be positive at positive AoA) + # Skip test if values are NaN + if !any(isnan.(sol.cl_group_array)) + @test all(sol.cl_group_array .> 0.0) + end + + finally + rm(settings_file; force=true) + end + end + + @testset "Group coefficients with n_groups=0 (no grouping)" begin + # Create a wing with no groups + n_panels = 20 + n_groups = 0 + + settings_file = create_temp_wing_settings("solver", "solver_test_wing.yaml"; alpha=5.0, beta=0.0, wind_speed=10.0) + + try + settings = VSMSettings(settings_file) + settings.wings[1].n_panels = n_panels + settings.wings[1].n_groups = n_groups + settings.solver_settings.n_panels = n_panels + settings.solver_settings.n_groups = n_groups + + wing = Wing(settings) + body_aero = BodyAerodynamics([wing]) + solver = Solver(body_aero, settings) + + va = [10.0, 0.0, 0.0] + set_va!(body_aero, va) + sol = solve!(solver, body_aero) + + # Test: Group arrays should be empty when n_groups=0 + @test length(sol.cl_group_array) == 0 + @test length(sol.cd_group_array) == 0 + @test length(sol.cm_group_array) == 0 + + finally + rm(settings_file; force=true) + end + end + + @testset "Group coefficients with different group sizes" begin + # Test with various panel/group combinations + test_cases = [ + (n_panels=40, n_groups=8), + (n_panels=30, n_groups=5), + (n_panels=24, n_groups=6), + ] + + for (n_panels, n_groups) in test_cases + settings_file = create_temp_wing_settings("solver", "solver_test_wing.yaml"; alpha=5.0, beta=0.0, wind_speed=10.0) + + try + settings = VSMSettings(settings_file) + settings.wings[1].n_panels = n_panels + settings.wings[1].n_groups = n_groups + settings.wings[1].grouping_method = EQUAL_SIZE + settings.solver_settings.n_panels = n_panels + settings.solver_settings.n_groups = n_groups + + wing = Wing(settings) + body_aero = BodyAerodynamics([wing]) + solver = Solver(body_aero, settings) + + va = [10.0, 0.0, 0.0] + set_va!(body_aero, va) + sol = solve!(solver, body_aero) + + # Verify arrays have correct size + @test length(sol.cl_group_array) == n_groups + @test length(sol.cd_group_array) == n_groups + @test length(sol.cm_group_array) == n_groups + + # Verify group coefficients are computed correctly + panels_per_group = n_panels ÷ n_groups + for group_idx in 1:n_groups + panel_start = (group_idx - 1) * panels_per_group + 1 + panel_end = group_idx * panels_per_group + + expected_cl = sum(sol.cl_array[panel_start:panel_end]) / panels_per_group + expected_cd = sum(sol.cd_array[panel_start:panel_end]) / panels_per_group + expected_cm = sum(sol.cm_array[panel_start:panel_end]) / panels_per_group + + # Handle NaN for all coefficients + if isnan(expected_cl) + @test isnan(sol.cl_group_array[group_idx]) + else + @test isapprox(sol.cl_group_array[group_idx], expected_cl, rtol=1e-10) + end + if isnan(expected_cd) + @test isnan(sol.cd_group_array[group_idx]) + else + @test isapprox(sol.cd_group_array[group_idx], expected_cd, rtol=1e-10) + end + if isnan(expected_cm) + @test isnan(sol.cm_group_array[group_idx]) + else + @test isapprox(sol.cm_group_array[group_idx], expected_cm, rtol=1e-10) + end + end + + finally + rm(settings_file; force=true) + end + end + end +end From 80fc35760d0c3c95923f74b25679f5a85eb292d3 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sat, 8 Nov 2025 13:59:55 +0100 Subject: [PATCH 15/86] Improved obj file reading --- src/obj_geometry.jl | 103 ++++++++++++++---- src/wing_geometry.jl | 3 +- test/Project.toml | 1 + test/TestSupport.jl | 5 - test/ram_geometry/test_kite_geometry.jl | 58 ++++++++-- test/runtests.jl | 3 +- test/settings/test_settings.jl | 2 +- test/solver/test_group_coefficients.jl | 4 - .../test_yaml_wing_deformation.jl | 6 - 9 files changed, 136 insertions(+), 49 deletions(-) delete mode 100644 test/TestSupport.jl diff --git a/src/obj_geometry.jl b/src/obj_geometry.jl index 1dae4cbc..dcf2a2e3 100644 --- a/src/obj_geometry.jl +++ b/src/obj_geometry.jl @@ -112,7 +112,8 @@ Create interpolation functions for leading/trailing edges and area. - Where le_interp and te_interp are tuples themselves, containing the x, y and z interpolations """ function create_interpolations(vertices, circle_center_z, radius, gamma_tip, R=I(3); interp_steps=40) - gamma_range = range(-gamma_tip+1e-6, gamma_tip-1e-6, interp_steps) + gamma_range = range(-gamma_tip+gamma_tip/interp_steps*2, + gamma_tip-gamma_tip/interp_steps*2, interp_steps) stepsize = gamma_range.step.hi vz_centered = [v[3] - circle_center_z for v in vertices] @@ -122,33 +123,91 @@ function create_interpolations(vertices, circle_center_z, radius, gamma_tip, R=I leading_edges = zeros(3, length(gamma_range)) areas = zeros(length(gamma_range)) + n_slices = length(gamma_range) for (j, gamma) in enumerate(gamma_range) trailing_edges[1, j] = -Inf leading_edges[1, j] = Inf - for (i, v) in enumerate(vertices) - # Rotate y coordinate to check box containment - # rotated_y = v[2] * cos(-gamma) - vz_centered[i] * sin(-gamma) - gamma_v = atan(-v[2], vz_centered[i]) - if gamma ≤ 0 && gamma - stepsize ≤ gamma_v ≤ gamma - if v[1] > trailing_edges[1, j] - trailing_edges[:, j] .= v - te_gammas[j] = gamma_v - end - if v[1] < leading_edges[1, j] - leading_edges[:, j] .= v - le_gammas[j] = gamma_v + + # Determine if this is a tip slice and get search parameters + is_first_tip = (j == 1) + is_last_tip = (j == n_slices) + + if is_first_tip || is_last_tip + # Tip slices: use directional search within adjacent slice region + gamma_search = is_first_tip ? gamma_range[1] : gamma_range[end] + max_te_score = -Inf + max_le_score = -Inf + + for (i, v) in enumerate(vertices) + gamma_v = atan(-v[2], vz_centered[i]) + + # Check if vertex is in the adjacent slice region + in_range = if gamma_search ≤ 0 + gamma_search - stepsize ≤ gamma_v ≤ gamma_search + else + gamma_search ≤ gamma_v ≤ gamma_search + stepsize end - elseif gamma > 0 && gamma ≤ gamma_v ≤ gamma + stepsize - if v[1] > trailing_edges[1, j] - trailing_edges[:, j] .= v - te_gammas[j] = gamma_v + + if in_range + if is_first_tip + # TE: furthest in [X, Y, -Z] direction + te_score = v[1] + v[2] - v[3] + if te_score > max_te_score + trailing_edges[:, j] .= v + te_gammas[j] = gamma_v + max_te_score = te_score + end + # LE: furthest in [-X, Y, -Z] direction + le_score = -v[1] + v[2] - v[3] + if le_score > max_le_score + leading_edges[:, j] .= v + le_gammas[j] = gamma_v + max_le_score = le_score + end + else # is_last_tip + # TE: furthest in [X, -Y, -Z] direction + te_score = v[1] - v[2] - v[3] + if te_score > max_te_score + trailing_edges[:, j] .= v + te_gammas[j] = gamma_v + max_te_score = te_score + end + # LE: furthest in [-X, -Y, -Z] direction + le_score = -v[1] - v[2] - v[3] + if le_score > max_le_score + leading_edges[:, j] .= v + le_gammas[j] = gamma_v + max_le_score = le_score + end + end end - if v[1] < leading_edges[1, j] - leading_edges[:, j] .= v - le_gammas[j] = gamma_v + end + else + # Interior slices: use standard min/max x-coordinate search + for (i, v) in enumerate(vertices) + gamma_v = atan(-v[2], vz_centered[i]) + if gamma ≤ 0 && gamma - stepsize ≤ gamma_v ≤ gamma + if v[1] > trailing_edges[1, j] + trailing_edges[:, j] .= v + te_gammas[j] = gamma_v + end + if v[1] < leading_edges[1, j] + leading_edges[:, j] .= v + le_gammas[j] = gamma_v + end + elseif gamma > 0 && gamma ≤ gamma_v ≤ gamma + stepsize + if v[1] > trailing_edges[1, j] + trailing_edges[:, j] .= v + te_gammas[j] = gamma_v + end + if v[1] < leading_edges[1, j] + leading_edges[:, j] .= v + le_gammas[j] = gamma_v + end end end end + area = norm(leading_edges[:, j] - trailing_edges[:, j]) * stepsize * radius last_area = j > 1 ? areas[j-1] : 0.0 areas[j] = last_area + area @@ -159,9 +218,9 @@ function create_interpolations(vertices, circle_center_z, radius, gamma_tip, R=I trailing_edges[:, j] .= R * trailing_edges[:, j] end - le_interp = ntuple(i -> linear_interpolation(te_gammas, leading_edges[i, :], + le_interp = ntuple(i -> linear_interpolation(le_gammas, leading_edges[i, :], extrapolation_bc=Line()), 3) - te_interp = ntuple(i -> linear_interpolation(le_gammas, trailing_edges[i, :], + te_interp = ntuple(i -> linear_interpolation(te_gammas, trailing_edges[i, :], extrapolation_bc=Line()), 3) area_interp = linear_interpolation(gamma_range, areas, extrapolation_bc=Line()) diff --git a/src/wing_geometry.jl b/src/wing_geometry.jl index 79554cb4..6ac62f48 100644 --- a/src/wing_geometry.jl +++ b/src/wing_geometry.jl @@ -462,7 +462,8 @@ function deform!(wing::Wing) local_y .= normalize(section1.LE_point - section2.LE_point) chord .= section1.TE_point .- section1.LE_point normal .= chord × local_y - @. wing.refined_sections[i].TE_point = section1.LE_point + cos(wing.theta_dist[i]) * chord - sin(wing.theta_dist[i]) * normal + @. wing.refined_sections[i].TE_point = section1.LE_point + + cos(wing.theta_dist[i]) * chord - sin(wing.theta_dist[i]) * normal end return nothing end diff --git a/test/Project.toml b/test/Project.toml index 9ede8c7a..7b362c6d 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -13,6 +13,7 @@ Serialization = "9e88b42a-f829-5b0c-bbe9-9e923198166b" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +VortexStepMethod = "ed3cd733-9f0f-46a9-93e0-89b8d4998dd9" YAML = "ddb6d928-2868-570f-bddf-ab3f9cf99eb6" [compat] diff --git a/test/TestSupport.jl b/test/TestSupport.jl deleted file mode 100644 index 4b428502..00000000 --- a/test/TestSupport.jl +++ /dev/null @@ -1,5 +0,0 @@ -module TestSupport -export suppress_warnings, test_data_path, create_temp_wing_settings, - get_standard_wing_file, get_complete_settings_file -include("test_data_utils.jl") -end \ No newline at end of file diff --git a/test/ram_geometry/test_kite_geometry.jl b/test/ram_geometry/test_kite_geometry.jl index 47dee1d4..861bc880 100644 --- a/test/ram_geometry/test_kite_geometry.jl +++ b/test/ram_geometry/test_kite_geometry.jl @@ -189,18 +189,18 @@ using Serialization # Create an ObjWing for testing wing = ObjWing(test_obj_path, test_dat_path; remove_nan=true) body_aero = BodyAerodynamics([wing]) - + # Store original TE point for comparison i = length(body_aero.panels) ÷ 2 original_te_point = copy(body_aero.panels[i].TE_point_1) - + # Apply deformation with non-zero angles theta_dist = fill(deg2rad(30.0), wing.n_panels) # 10 degrees twist delta_dist = fill(deg2rad(5.0), wing.n_panels) # 5 degrees trailing edge deflection - + VortexStepMethod.deform!(wing, theta_dist, delta_dist) VortexStepMethod.reinit!(body_aero) - + # Check if TE point changed after deformation deformed_te_point = copy(body_aero.panels[i].TE_point_1) @test !isapprox(original_te_point, deformed_te_point, atol=1e-2) @@ -208,19 +208,61 @@ using Serialization @test deformed_te_point[2] ≈ original_te_point[2] atol=1e-2 # right hand rule @test deformed_te_point[1] < original_te_point[1] # right hand rule @test body_aero.panels[i].delta ≈ deg2rad(5.0) - + # Reset deformation with zero angles zero_theta_dist = zeros(wing.n_panels) zero_delta_dist = zeros(wing.n_panels) - + VortexStepMethod.deform!(wing, zero_theta_dist, zero_delta_dist) VortexStepMethod.reinit!(body_aero) - + # Check if TE point returned to original position reset_te_point = copy(body_aero.panels[i].TE_point_1) @test original_te_point ≈ reset_te_point atol=1e-4 end + + @testset "First and Last Section Deformation with group_deform!" begin + # Create an ObjWing with a small number of panels and groups + wing = ObjWing(test_obj_path, test_dat_path; + n_panels=4, n_groups=2, remove_nan=true) + + # Store original TE points from all refined_sections + # Wing has n_panels+1 sections (5 sections for 4 panels) + n_sections = wing.n_panels + 1 + original_te_points = [copy(wing.refined_sections[i].TE_point) + for i in 1:n_sections] + + @show wing.refined_sections[1].LE_point + @show wing.refined_sections[1].TE_point + @show wing.refined_sections[end].LE_point + @show wing.refined_sections[end].TE_point + + # Apply group_deform! with non-zero angles (2 groups, each controlling 2 panels) + theta_angles = [deg2rad(15.0), deg2rad(20.0)] + delta_angles = [deg2rad(5.0), deg2rad(10.0)] + + VortexStepMethod.group_deform!(wing, theta_angles, delta_angles; smooth=false) + + # Check that all sections' TE points have been deformed + for i in 1:n_sections + deformed_te = wing.refined_sections[i].TE_point + original_te = original_te_points[i] + + if i == 1 + # First section should be deformed + @test !isapprox(original_te, deformed_te, atol=1e-6) + @info "Section 1 (first): original=$original_te, deformed=$deformed_te" + elseif i == n_sections + # Last section (n_panels+1) should be deformed + @test !isapprox(original_te, deformed_te, atol=1e-6) + @info "Section $(n_sections) (last): original=$original_te, deformed=$deformed_te" + else + # Intermediate sections should also be deformed + @test !isapprox(original_te, deformed_te, atol=1e-6) + end + end + end rm(test_obj_path) rm(test_dat_path) -end \ No newline at end of file +end diff --git a/test/runtests.jl b/test/runtests.jl index 520eeab3..f89bea03 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -2,8 +2,7 @@ using Test, VortexStepMethod # Make paths robust (avoid cd("..")) cd(@__DIR__) # ensure we're in test/ no matter how tests are launched -include("TestSupport.jl") -using .TestSupport +include("test_data_utils.jl") println("Running tests...") diff --git a/test/settings/test_settings.jl b/test/settings/test_settings.jl index 37b3d920..e3200766 100644 --- a/test/settings/test_settings.jl +++ b/test/settings/test_settings.jl @@ -11,6 +11,6 @@ using Test @test vss.wings isa Vector{WingSettings} @test length(vss.wings) == 2 io = IOBuffer(repr(vss)) - @test countlines(io) == 44 # Updated to match new output format + @test countlines(io) == 46 # Updated to match new output format end nothing diff --git a/test/solver/test_group_coefficients.jl b/test/solver/test_group_coefficients.jl index 7eae60ef..ede46b2a 100644 --- a/test/solver/test_group_coefficients.jl +++ b/test/solver/test_group_coefficients.jl @@ -2,10 +2,6 @@ using VortexStepMethod using LinearAlgebra using Test -# Load test support -include("../TestSupport.jl") -using .TestSupport - @testset "Group Coefficient Arrays Tests" begin @testset "Group coefficients with EQUAL_SIZE method" begin # Create a simple wing with groups diff --git a/test/yaml_geometry/test_yaml_wing_deformation.jl b/test/yaml_geometry/test_yaml_wing_deformation.jl index 580e3dc9..578528b2 100644 --- a/test/yaml_geometry/test_yaml_wing_deformation.jl +++ b/test/yaml_geometry/test_yaml_wing_deformation.jl @@ -2,12 +2,6 @@ using VortexStepMethod using LinearAlgebra using Test -# Load TestSupport if not already loaded (for standalone execution) -if !@isdefined(TestSupport) - include(joinpath(@__DIR__, "..", "TestSupport.jl")) - using .TestSupport -end - @testset "YAML Wing Deformation Tests" begin @testset "Simple Wing Deformation" begin # Load existing simple_wing.yaml From b3ef2b0a1b597d5e5d65136ec15c9896a53e4b6c Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sat, 8 Nov 2025 14:11:12 +0100 Subject: [PATCH 16/86] Fixed deform --- src/wing_geometry.jl | 37 ++++++++++++++---- test/ram_geometry/test_kite_geometry.jl | 5 --- test/runtests.jl | 52 +++++++++++++++++-------- 3 files changed, 65 insertions(+), 29 deletions(-) diff --git a/src/wing_geometry.jl b/src/wing_geometry.jl index 6ac62f48..c212e8ab 100644 --- a/src/wing_geometry.jl +++ b/src/wing_geometry.jl @@ -456,14 +456,37 @@ function deform!(wing::Wing) chord = zeros(MVec3) normal = zeros(MVec3) - for i in 1:wing.n_panels - section1 = wing.non_deformed_sections[i] - section2 = wing.non_deformed_sections[i+1] - local_y .= normalize(section1.LE_point - section2.LE_point) - chord .= section1.TE_point .- section1.LE_point + # Process all sections (n_panels + 1) + # Each section gets angle(s) from adjacent panel(s) + for i in 1:(wing.n_panels + 1) + section = wing.non_deformed_sections[i] + + # Determine the angle for this section + if i == 1 + # First section: use angle from first panel + theta = wing.theta_dist[1] + elseif i == wing.n_panels + 1 + # Last section: use angle from last panel + theta = wing.theta_dist[wing.n_panels] + else + # Middle sections: average of adjacent panels + theta = 0.5 * (wing.theta_dist[i-1] + wing.theta_dist[i]) + end + + # Compute local coordinate system + if i < wing.n_panels + 1 + section2 = wing.non_deformed_sections[i+1] + local_y .= normalize(section.LE_point - section2.LE_point) + else + # For last section, use same local_y as previous + section_prev = wing.non_deformed_sections[i-1] + local_y .= normalize(section_prev.LE_point - section.LE_point) + end + + chord .= section.TE_point .- section.LE_point normal .= chord × local_y - @. wing.refined_sections[i].TE_point = section1.LE_point + - cos(wing.theta_dist[i]) * chord - sin(wing.theta_dist[i]) * normal + @. wing.refined_sections[i].TE_point = section.LE_point + + cos(theta) * chord - sin(theta) * normal end return nothing end diff --git a/test/ram_geometry/test_kite_geometry.jl b/test/ram_geometry/test_kite_geometry.jl index 861bc880..4eb07823 100644 --- a/test/ram_geometry/test_kite_geometry.jl +++ b/test/ram_geometry/test_kite_geometry.jl @@ -232,11 +232,6 @@ using Serialization original_te_points = [copy(wing.refined_sections[i].TE_point) for i in 1:n_sections] - @show wing.refined_sections[1].LE_point - @show wing.refined_sections[1].TE_point - @show wing.refined_sections[end].LE_point - @show wing.refined_sections[end].TE_point - # Apply group_deform! with non-zero angles (2 groups, each controlling 2 panels) theta_angles = [deg2rad(15.0), deg2rad(20.0)] delta_angles = [deg2rad(5.0), deg2rad(10.0)] diff --git a/test/runtests.jl b/test/runtests.jl index f89bea03..7a2abdd5 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -4,7 +4,25 @@ using Test, VortexStepMethod cd(@__DIR__) # ensure we're in test/ no matter how tests are launched include("test_data_utils.jl") +# Support selective test execution via ]test test_args=["pattern"] +const test_patterns = isempty(ARGS) ? String[] : ARGS + println("Running tests...") +if !isempty(test_patterns) + println("Filtering tests matching: ", test_patterns) +end + +# Helper to check if a test file matches any pattern +function should_run_test(test_path::String) + isempty(test_patterns) && return true + for pattern in test_patterns + # Match directory (e.g., "solver") or specific file (e.g., "test_group_coefficients") + if occursin(pattern, test_path) + return true + end + end + return false +end # keep your env check as-is... const build_is_production_build_env_name = "BUILD_IS_PRODUCTION_BUILD" @@ -14,25 +32,25 @@ const build_is_production_build = let v = get(ENV, build_is_production_build_env end::Bool @testset verbose = true "Testing VortexStepMethod..." begin - if build_is_production_build + if build_is_production_build && should_run_test("bench") include("bench.jl") end - include("body_aerodynamics/test_body_aerodynamics.jl") - include("body_aerodynamics/test_results.jl") - include("filament/test_bound_filament.jl") - include("filament/test_semi_infinite_filament.jl") - include("panel/test_panel.jl") - include("plotting/test_plotting.jl") - include("polars/test_polars.jl") - include("ram_geometry/test_kite_geometry.jl") - include("settings/test_settings.jl") - include("solver/test_solver.jl") - include("solver/test_group_coefficients.jl") - include("VortexStepMethod/test_VortexStepMethod.jl") - include("wake/test_wake.jl") - include("wing_geometry/test_wing_geometry.jl") - include("yaml_geometry/test_yaml_geometry.jl") - include("Aqua.jl") + should_run_test("body_aerodynamics/test_body_aerodynamics.jl") && include("body_aerodynamics/test_body_aerodynamics.jl") + should_run_test("body_aerodynamics/test_results.jl") && include("body_aerodynamics/test_results.jl") + should_run_test("filament/test_bound_filament.jl") && include("filament/test_bound_filament.jl") + should_run_test("filament/test_semi_infinite_filament.jl") && include("filament/test_semi_infinite_filament.jl") + should_run_test("panel/test_panel.jl") && include("panel/test_panel.jl") + should_run_test("plotting/test_plotting.jl") && include("plotting/test_plotting.jl") + should_run_test("polars/test_polars.jl") && include("polars/test_polars.jl") + should_run_test("ram_geometry/test_kite_geometry.jl") && include("ram_geometry/test_kite_geometry.jl") + should_run_test("settings/test_settings.jl") && include("settings/test_settings.jl") + should_run_test("solver/test_solver.jl") && include("solver/test_solver.jl") + should_run_test("solver/test_group_coefficients.jl") && include("solver/test_group_coefficients.jl") + should_run_test("VortexStepMethod/test_VortexStepMethod.jl") && include("VortexStepMethod/test_VortexStepMethod.jl") + should_run_test("wake/test_wake.jl") && include("wake/test_wake.jl") + should_run_test("wing_geometry/test_wing_geometry.jl") && include("wing_geometry/test_wing_geometry.jl") + should_run_test("yaml_geometry/test_yaml_geometry.jl") && include("yaml_geometry/test_yaml_geometry.jl") + should_run_test("Aqua.jl") && include("Aqua.jl") end nothing From 8e28721446031a55ec1b6cfd2e523d165d37c065 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sat, 8 Nov 2025 14:19:28 +0100 Subject: [PATCH 17/86] Test on 1.10 and 1.11 --- .github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 6407e6c9..48fdc83d 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -23,7 +23,7 @@ jobs: matrix: version: - '1.10' - - '1' + - '1.11' os: - ubuntu-latest build_is_production_build: From a6a8337f85ab814ed86a85dcd0bd084cd217e842 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sat, 8 Nov 2025 17:00:37 +0100 Subject: [PATCH 18/86] Disable mapping kwarg --- src/body_aerodynamics.jl | 9 ++++++--- src/wing_geometry.jl | 22 ++++++++++++++-------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/body_aerodynamics.jl b/src/body_aerodynamics.jl index 103745dc..a05a289b 100644 --- a/src/body_aerodynamics.jl +++ b/src/body_aerodynamics.jl @@ -114,7 +114,7 @@ function Base.setproperty!(obj::BodyAerodynamics, sym::Symbol, val) end """ - reinit!(body_aero::BodyAerodynamics; init_aero, va, omega, refine_mesh) + reinit!(body_aero::BodyAerodynamics; init_aero, va, omega, refine_mesh, recompute_mapping) Initialize a BodyAerodynamics struct in-place by setting up panels and coefficients. @@ -127,6 +127,8 @@ Initialize a BodyAerodynamics struct in-place by setting up panels and coefficie - `omega=zeros(3)`: Turn rate in kite body frame x y and z - `refine_mesh=true`: Whether to refine wing meshes. Set to `false` after `deform!()` to preserve deformed geometry. +- `recompute_mapping=true`: Whether to recompute the refined panel mapping. + Set to `false` to skip mapping computation when it hasn't changed. # Returns nothing @@ -135,12 +137,13 @@ function reinit!(body_aero::BodyAerodynamics; init_aero=true, va=[15.0, 0.0, 0.0], omega=zeros(MVec3), - refine_mesh=true + refine_mesh=true, + recompute_mapping=true ) idx = 1 vec = @MVector zeros(3) for wing in body_aero.wings - reinit!(wing; refine_mesh=refine_mesh) + reinit!(wing; refine_mesh, recompute_mapping) panel_props = wing.panel_props # Create panels diff --git a/src/wing_geometry.jl b/src/wing_geometry.jl index c212e8ab..a5bcdbce 100644 --- a/src/wing_geometry.jl +++ b/src/wing_geometry.jl @@ -302,18 +302,20 @@ function Wing(n_panels::Int; end """ - reinit!(wing::AbstractWing; refine_mesh=true) + reinit!(wing::AbstractWing; refine_mesh=true, recompute_mapping=true) Reinitialize wing geometry and panel properties. # Keyword Arguments - `refine_mesh::Bool=true`: Whether to refine the mesh. Set to `false` after `deform!()` to preserve deformed geometry while updating panel properties. +- `recompute_mapping::Bool=true`: Whether to recompute the refined panel mapping. + Set to `false` to skip mapping computation when it hasn't changed. """ -function reinit!(wing::AbstractWing; refine_mesh=true) +function reinit!(wing::AbstractWing; refine_mesh=true, recompute_mapping=true) # Refine mesh unless explicitly disabled (e.g., to preserve deformation) if refine_mesh - refine_aerodynamic_mesh!(wing) + refine_aerodynamic_mesh!(wing; recompute_mapping) end # Calculate panel properties @@ -587,14 +589,18 @@ function update_non_deformed_sections!(wing::AbstractWing) end """ - refine_aerodynamic_mesh!(wing::AbstractWing) + refine_aerodynamic_mesh!(wing::AbstractWing; recompute_mapping=true) Refine the aerodynamic mesh of the wing based on spanwise panel distribution. +# Keyword Arguments +- `recompute_mapping::Bool=true`: Whether to recompute the refined panel mapping. + Set to `false` to skip mapping computation when it hasn't changed. + Returns: Vector{Section}: List of refined sections """ -function refine_aerodynamic_mesh!(wing::AbstractWing) +function refine_aerodynamic_mesh!(wing::AbstractWing; recompute_mapping=true) sort!(wing.sections, by=s -> s.LE_point[2], rev=true) n_sections = wing.n_panels + 1 if length(wing.refined_sections) == 0 @@ -631,7 +637,7 @@ function refine_aerodynamic_mesh!(wing::AbstractWing) for i in eachindex(wing.sections) reinit!(wing.refined_sections[i], wing.sections[i]) end - compute_refined_panel_mapping!(wing) + recompute_mapping && compute_refined_panel_mapping!(wing) update_non_deformed_sections!(wing) return nothing end @@ -642,7 +648,7 @@ function refine_aerodynamic_mesh!(wing::AbstractWing) if n_sections == 2 reinit!(wing.refined_sections[1], LE[1,:], TE[1,:], aero_model[1], aero_data[1]) reinit!(wing.refined_sections[2], LE[end,:], TE[end,:], aero_model[end], aero_data[end]) - compute_refined_panel_mapping!(wing) + recompute_mapping && compute_refined_panel_mapping!(wing) update_non_deformed_sections!(wing) return nothing end @@ -666,7 +672,7 @@ function refine_aerodynamic_mesh!(wing::AbstractWing) end # Compute panel mapping by finding closest unrefined panel for each refined panel - compute_refined_panel_mapping!(wing) + recompute_mapping && compute_refined_panel_mapping!(wing) # Validate REFINE grouping method if wing.grouping_method == REFINE && wing.n_groups > 0 From 3502599eb0f7c2f1d1a54473ae519d5c5de78ed5 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sat, 8 Nov 2025 17:33:57 +0100 Subject: [PATCH 19/86] Add kwarg to sort sections --- src/body_aerodynamics.jl | 9 ++++++--- src/wing_geometry.jl | 17 +++++++++++------ 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/body_aerodynamics.jl b/src/body_aerodynamics.jl index a05a289b..5d5ca33f 100644 --- a/src/body_aerodynamics.jl +++ b/src/body_aerodynamics.jl @@ -114,7 +114,7 @@ function Base.setproperty!(obj::BodyAerodynamics, sym::Symbol, val) end """ - reinit!(body_aero::BodyAerodynamics; init_aero, va, omega, refine_mesh, recompute_mapping) + reinit!(body_aero::BodyAerodynamics; init_aero, va, omega, refine_mesh, recompute_mapping, sort_sections) Initialize a BodyAerodynamics struct in-place by setting up panels and coefficients. @@ -129,6 +129,8 @@ Initialize a BodyAerodynamics struct in-place by setting up panels and coefficie `deform!()` to preserve deformed geometry. - `recompute_mapping=true`: Whether to recompute the refined panel mapping. Set to `false` to skip mapping computation when it hasn't changed. +- `sort_sections=true`: Whether to sort sections by spanwise position. + Set to `false` for REFINE wings where section order is determined by structural connectivity. # Returns nothing @@ -138,12 +140,13 @@ function reinit!(body_aero::BodyAerodynamics; va=[15.0, 0.0, 0.0], omega=zeros(MVec3), refine_mesh=true, - recompute_mapping=true + recompute_mapping=true, + sort_sections=true ) idx = 1 vec = @MVector zeros(3) for wing in body_aero.wings - reinit!(wing; refine_mesh, recompute_mapping) + reinit!(wing; refine_mesh, recompute_mapping, sort_sections) panel_props = wing.panel_props # Create panels diff --git a/src/wing_geometry.jl b/src/wing_geometry.jl index a5bcdbce..83889eff 100644 --- a/src/wing_geometry.jl +++ b/src/wing_geometry.jl @@ -302,7 +302,7 @@ function Wing(n_panels::Int; end """ - reinit!(wing::AbstractWing; refine_mesh=true, recompute_mapping=true) + reinit!(wing::AbstractWing; refine_mesh=true, recompute_mapping=true, sort_sections=true) Reinitialize wing geometry and panel properties. @@ -311,11 +311,13 @@ Reinitialize wing geometry and panel properties. `deform!()` to preserve deformed geometry while updating panel properties. - `recompute_mapping::Bool=true`: Whether to recompute the refined panel mapping. Set to `false` to skip mapping computation when it hasn't changed. +- `sort_sections::Bool=true`: Whether to sort sections by spanwise position. + Set to `false` for REFINE wings where section order is determined by structural connectivity. """ -function reinit!(wing::AbstractWing; refine_mesh=true, recompute_mapping=true) +function reinit!(wing::AbstractWing; refine_mesh=true, recompute_mapping=true, sort_sections=true) # Refine mesh unless explicitly disabled (e.g., to preserve deformation) if refine_mesh - refine_aerodynamic_mesh!(wing; recompute_mapping) + refine_aerodynamic_mesh!(wing; recompute_mapping, sort_sections) end # Calculate panel properties @@ -589,19 +591,22 @@ function update_non_deformed_sections!(wing::AbstractWing) end """ - refine_aerodynamic_mesh!(wing::AbstractWing; recompute_mapping=true) + refine_aerodynamic_mesh!(wing::AbstractWing; recompute_mapping=true, sort_sections=true) Refine the aerodynamic mesh of the wing based on spanwise panel distribution. # Keyword Arguments - `recompute_mapping::Bool=true`: Whether to recompute the refined panel mapping. Set to `false` to skip mapping computation when it hasn't changed. +- `sort_sections::Bool=true`: Whether to sort sections by spanwise position (y-coordinate). + Set to `false` for REFINE wings where section order is determined by structural connectivity. Returns: Vector{Section}: List of refined sections """ -function refine_aerodynamic_mesh!(wing::AbstractWing; recompute_mapping=true) - sort!(wing.sections, by=s -> s.LE_point[2], rev=true) +function refine_aerodynamic_mesh!(wing::AbstractWing; recompute_mapping=true, sort_sections=true) + # Only sort sections if requested (skip for REFINE wings with fixed structural order) + sort_sections && sort!(wing.sections, by=s -> s.LE_point[2], rev=true) n_sections = wing.n_panels + 1 if length(wing.refined_sections) == 0 if wing.spanwise_distribution == UNCHANGED || length(wing.sections) == n_sections From f55597f729d9755cd44cdd017ef5de2e7f397467 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sat, 8 Nov 2025 18:36:12 +0100 Subject: [PATCH 20/86] Add groups --- src/body_aerodynamics.jl | 12 +++++++-- src/solver.jl | 53 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 61 insertions(+), 4 deletions(-) diff --git a/src/body_aerodynamics.jl b/src/body_aerodynamics.jl index 5d5ca33f..b96ff57d 100644 --- a/src/body_aerodynamics.jl +++ b/src/body_aerodynamics.jl @@ -24,6 +24,7 @@ Main structure for calculating aerodynamic properties of bodies. Use the constru @with_kw mutable struct BodyAerodynamics{P} panels::Vector{Panel} wings::Vector{Wing} + groups::Vector{Panel} = Panel[] _va::MVec3 = zeros(MVec3) omega::MVec3 = zeros(MVec3) gamma_distribution::MVector{P, Float64} = zeros(P) @@ -73,6 +74,7 @@ function BodyAerodynamics( ) where T <: AbstractWing # Initialize panels panels = Panel[] + n_groups = 0 for wing in wings for section in wing.sections section.LE_point .-= kite_body_origin @@ -80,7 +82,7 @@ function BodyAerodynamics( end if wing.spanwise_distribution == UNCHANGED wing.refined_sections = wing.sections - !(wing.n_panels == length(wing.sections) - 1) && + !(wing.n_panels == length(wing.sections) - 1) && throw(ArgumentError("(wing.n_panels = $(wing.n_panels)) != (length(wing.sections) - 1 = $(length(wing.sections) - 1))")) else wing.refined_sections = Section[Section() for _ in 1:wing.n_panels+1] @@ -91,9 +93,15 @@ function BodyAerodynamics( panel = Panel() push!(panels, panel) end + + # Count total groups + n_groups += wing.n_groups end - body_aero = BodyAerodynamics{length(panels)}(; panels, wings) + # Initialize groups (unrefined panel representatives) + groups = [Panel() for _ in 1:n_groups] + + body_aero = BodyAerodynamics{length(panels)}(; panels, wings, groups) reinit!(body_aero; va, omega) return body_aero end diff --git a/src/solver.jl b/src/solver.jl index 742d921b..ed6f524b 100644 --- a/src/solver.jl +++ b/src/solver.jl @@ -316,43 +316,92 @@ function solve!(solver::Solver, body_aero::BodyAerodynamics, gamma_distribution= panels_per_group = wing.n_panels ÷ wing.n_groups for _ in 1:wing.n_groups panel_count = 0 + group_panel = body_aero.groups[group_idx] + # Zero out accumulated fields + group_panel.x_airf .= 0.0 + group_panel.y_airf .= 0.0 + group_panel.z_airf .= 0.0 + group_panel.va .= 0.0 + group_panel.chord = 0.0 + group_panel.width = 0.0 for _ in 1:panels_per_group + panel = body_aero.panels[panel_idx] group_moment_dist[group_idx] += moment_dist[panel_idx] group_moment_coeff_dist[group_idx] += moment_coeff_dist[panel_idx] cl_group_array[group_idx] += solver.sol.cl_array[panel_idx] cd_group_array[group_idx] += solver.sol.cd_array[panel_idx] cm_group_array[group_idx] += solver.sol.cm_array[panel_idx] + # Accumulate geometry for averaging + group_panel.x_airf .+= panel.x_airf + group_panel.y_airf .+= panel.y_airf + group_panel.z_airf .+= panel.z_airf + group_panel.va .+= panel.va + group_panel.chord += panel.chord + group_panel.width += panel.width panel_idx += 1 panel_count += 1 end - # Average the coefficients over panels in the group + # Average the coefficients and geometry over panels in the group cl_group_array[group_idx] /= panel_count cd_group_array[group_idx] /= panel_count cm_group_array[group_idx] /= panel_count + group_panel.x_airf ./= panel_count + group_panel.y_airf ./= panel_count + group_panel.z_airf ./= panel_count + group_panel.va ./= panel_count + group_panel.chord /= panel_count + group_panel.width /= panel_count group_idx += 1 end elseif wing.grouping_method == REFINE # REFINE method: group refined panels by their original unrefined section + # Initialize group panels + for i in 1:wing.n_groups + target_group_idx = group_idx + i - 1 + group_panel = body_aero.groups[target_group_idx] + group_panel.x_airf .= 0.0 + group_panel.y_airf .= 0.0 + group_panel.z_airf .= 0.0 + group_panel.va .= 0.0 + group_panel.chord = 0.0 + group_panel.width = 0.0 + end # First pass: accumulate values group_panel_counts = zeros(Int, wing.n_groups) for local_panel_idx in 1:wing.n_panels + panel = body_aero.panels[panel_idx] original_section_idx = wing.refined_panel_mapping[local_panel_idx] target_group_idx = group_idx + original_section_idx - 1 + group_panel = body_aero.groups[target_group_idx] group_moment_dist[target_group_idx] += moment_dist[panel_idx] group_moment_coeff_dist[target_group_idx] += moment_coeff_dist[panel_idx] cl_group_array[target_group_idx] += solver.sol.cl_array[panel_idx] cd_group_array[target_group_idx] += solver.sol.cd_array[panel_idx] cm_group_array[target_group_idx] += solver.sol.cm_array[panel_idx] + # Accumulate geometry + group_panel.x_airf .+= panel.x_airf + group_panel.y_airf .+= panel.y_airf + group_panel.z_airf .+= panel.z_airf + group_panel.va .+= panel.va + group_panel.chord += panel.chord + group_panel.width += panel.width group_panel_counts[original_section_idx] += 1 panel_idx += 1 end - # Second pass: average coefficients + # Second pass: average coefficients and geometry for i in 1:wing.n_groups target_group_idx = group_idx + i - 1 if group_panel_counts[i] > 0 + group_panel = body_aero.groups[target_group_idx] cl_group_array[target_group_idx] /= group_panel_counts[i] cd_group_array[target_group_idx] /= group_panel_counts[i] cm_group_array[target_group_idx] /= group_panel_counts[i] + group_panel.x_airf ./= group_panel_counts[i] + group_panel.y_airf ./= group_panel_counts[i] + group_panel.z_airf ./= group_panel_counts[i] + group_panel.va ./= group_panel_counts[i] + group_panel.chord /= group_panel_counts[i] + group_panel.width /= group_panel_counts[i] end end group_idx += wing.n_groups From 872bdfd7e4df92ff75c4493edd8128b38bbb6a6c Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sun, 9 Nov 2025 14:00:50 +0100 Subject: [PATCH 21/86] Correct width --- src/solver.jl | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/solver.jl b/src/solver.jl index ed6f524b..cb7cc6be 100644 --- a/src/solver.jl +++ b/src/solver.jl @@ -54,6 +54,7 @@ Struct for storing the solution of the [solve!](@ref) function. Must contain all cl_group_array::MVector{G, Float64} = zeros(G) cd_group_array::MVector{G, Float64} = zeros(G) cm_group_array::MVector{G, Float64} = zeros(G) + alpha_group_array::MVector{G, Float64} = zeros(G) solver_status::SolverStatus = FAILURE end @@ -302,11 +303,13 @@ function solve!(solver::Solver, body_aero::BodyAerodynamics, gamma_distribution= cl_group_array = solver.sol.cl_group_array cd_group_array = solver.sol.cd_group_array cm_group_array = solver.sol.cm_group_array + alpha_group_array = solver.sol.alpha_group_array group_moment_dist .= 0.0 group_moment_coeff_dist .= 0.0 cl_group_array .= 0.0 cd_group_array .= 0.0 cm_group_array .= 0.0 + alpha_group_array .= 0.0 panel_idx = 1 group_idx = 1 for wing in body_aero.wings @@ -331,6 +334,7 @@ function solve!(solver::Solver, body_aero::BodyAerodynamics, gamma_distribution= cl_group_array[group_idx] += solver.sol.cl_array[panel_idx] cd_group_array[group_idx] += solver.sol.cd_array[panel_idx] cm_group_array[group_idx] += solver.sol.cm_array[panel_idx] + alpha_group_array[group_idx] += solver.sol.alpha_array[panel_idx] # Accumulate geometry for averaging group_panel.x_airf .+= panel.x_airf group_panel.y_airf .+= panel.y_airf @@ -345,12 +349,12 @@ function solve!(solver::Solver, body_aero::BodyAerodynamics, gamma_distribution= cl_group_array[group_idx] /= panel_count cd_group_array[group_idx] /= panel_count cm_group_array[group_idx] /= panel_count + alpha_group_array[group_idx] /= panel_count group_panel.x_airf ./= panel_count group_panel.y_airf ./= panel_count group_panel.z_airf ./= panel_count group_panel.va ./= panel_count group_panel.chord /= panel_count - group_panel.width /= panel_count group_idx += 1 end elseif wing.grouping_method == REFINE @@ -378,6 +382,7 @@ function solve!(solver::Solver, body_aero::BodyAerodynamics, gamma_distribution= cl_group_array[target_group_idx] += solver.sol.cl_array[panel_idx] cd_group_array[target_group_idx] += solver.sol.cd_array[panel_idx] cm_group_array[target_group_idx] += solver.sol.cm_array[panel_idx] + alpha_group_array[target_group_idx] += solver.sol.alpha_array[panel_idx] # Accumulate geometry group_panel.x_airf .+= panel.x_airf group_panel.y_airf .+= panel.y_airf @@ -396,6 +401,7 @@ function solve!(solver::Solver, body_aero::BodyAerodynamics, gamma_distribution= cl_group_array[target_group_idx] /= group_panel_counts[i] cd_group_array[target_group_idx] /= group_panel_counts[i] cm_group_array[target_group_idx] /= group_panel_counts[i] + alpha_group_array[target_group_idx] /= group_panel_counts[i] group_panel.x_airf ./= group_panel_counts[i] group_panel.y_airf ./= group_panel_counts[i] group_panel.z_airf ./= group_panel_counts[i] From a1df71207653e22e5b716a6824659d2ffefc9dd4 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Mon, 10 Nov 2025 16:15:32 +0100 Subject: [PATCH 22/86] Add makie plotting --- examples/Project.toml | 1 + examples/ram_air_kite.jl | 4 +- ext/VortexStepMethodControlPlotsExt.jl | 920 ++++++++++++++++++++++++- ext/VortexStepMethodMakieExt.jl | 690 ++++++++++++++++++- src/panel.jl | 2 +- src/plotting.jl | 920 ------------------------- 6 files changed, 1612 insertions(+), 925 deletions(-) delete mode 100644 src/plotting.jl diff --git a/examples/Project.toml b/examples/Project.toml index b94307b9..fea9b2fd 100644 --- a/examples/Project.toml +++ b/examples/Project.toml @@ -2,6 +2,7 @@ CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" ControlPlots = "23c2ee80-7a9e-4350-b264-8e670f12517c" DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" +GLMakie = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" VortexStepMethod = "ed3cd733-9f0f-46a9-93e0-89b8d4998dd9" diff --git a/examples/ram_air_kite.jl b/examples/ram_air_kite.jl index 13e60c62..bbf1480b 100644 --- a/examples/ram_air_kite.jl +++ b/examples/ram_air_kite.jl @@ -1,4 +1,4 @@ -using ControlPlots +using GLMakie using VortexStepMethod using LinearAlgebra @@ -118,4 +118,4 @@ PLOT && plot_polars( is_show=true, use_tex=USE_TEX ) -nothing \ No newline at end of file +nothing diff --git a/ext/VortexStepMethodControlPlotsExt.jl b/ext/VortexStepMethodControlPlotsExt.jl index ce9494be..b2d09e9f 100644 --- a/ext/VortexStepMethodControlPlotsExt.jl +++ b/ext/VortexStepMethodControlPlotsExt.jl @@ -5,6 +5,924 @@ import VortexStepMethod: calculate_filaments_for_plotting export plot_wing, plot_circulation_distribution, plot_geometry, plot_distribution, plot_polars, save_plot, show_plot, plot_polar_data -include("../src/plotting.jl") +""" + set_plot_style(titel_size=16; use_tex=false) + +Set the default style for plots using LaTeX. +`` +# Arguments: +- `titel_size`: size of the plot title in points (default: 16) +- `ùse_tex`: if the external `pdflatex` command shall be used +""" +function set_plot_style(titel_size=16; use_tex=false) + rcParams = plt.PyDict(plt.matplotlib."rcParams") + rcParams["text.usetex"] = use_tex + rcParams["font.family"] = "serif" + if use_tex + rcParams["font.serif"] = ["Computer Modern Roman"] + end + rcParams["axes.titlesize"] = titel_size + rcParams["axes.labelsize"] = 12 + rcParams["axes.linewidth"] = 1 + rcParams["lines.linewidth"] = 1 + rcParams["lines.markersize"] = 6 + rcParams["xtick.labelsize"] = 10 + rcParams["ytick.labelsize"] = 10 + rcParams["legend.fontsize"] = 10 + rcParams["figure.titlesize"] = 16 + if use_tex + rcParams["pgf.texsystem"] = "pdflatex" # Use pdflatex + end + rcParams["pgf.rcfonts"] = false + rcParams["figure.figsize"] = (10, 6) # Default figure size +end + + +""" + save_plot(fig, save_path, title; data_type=".pdf") + +Save a plot to a file. + +# Arguments +- `fig`: Plots figure object +- `save_path`: Path to save the plot +- `title`: Title of the plot + +# Keyword arguments +- `data_type`: File extension (default: ".pdf") +""" +function VortexStepMethod.save_plot(fig, save_path, title; data_type=".pdf") + isnothing(save_path) && throw(ArgumentError("save_path should be provided")) + + !isdir(save_path) && mkpath(save_path) + full_path = joinpath(save_path, title * data_type) + + @debug "Attempting to save figure to: $full_path" + @debug "Current working directory: $(pwd())" + + try + fig.savefig(full_path) + @debug "Figure saved as $data_type" + + if isfile(full_path) + @debug "File successfully saved to $full_path" + @debug "File size: $(filesize(full_path)) bytes" + else + @info "File does not exist after save attempt: $full_path" + end + catch e + @error "Error saving figure: $e" + @error "Error type: $(typeof(e))" + rethrow(e) + end +end + +""" + show_plot(fig; dpi=130) + +Display a plot at specified DPI. + +# Arguments +- `fig`: Plots figure object + +# Keyword arguments +- `dpi`: Dots per inch for the figure (default: 130) +""" +function VortexStepMethod.show_plot(fig; dpi=130) + plt.display(fig) +end + +""" + plot_line_segment!(ax, segment, color, label; width=3) + +Plot a line segment in 3D with arrow. + +# Arguments +- `ax`: Plot axis +- `segment`: Array of two points defining the segment +- `color`: Color of the segment +- `label`: Label for the legend + +# Keyword Arguments +- `width`: Line width (default: 3) +""" +function plot_line_segment!(ax, segment, color, label; width=3) + ax.plot( + [segment[1][1], segment[2][1]], + [segment[1][2], segment[2][2]], + [segment[1][3], segment[2][3]], + color=color, label=label, linewidth=width + ) + + dir = segment[2] - segment[1] + ax.quiver( + [segment[1][1]], [segment[1][2]], [segment[1][3]], + [dir[1]], [dir[2]], [dir[3]], + color=color + ) +end + +""" + set_axes_equal!(ax; zoom=1.8) + +Set 3D plot axes to equal scale. + +# Arguments +- ax: 3D plot axis + +# Keyword arguments +zoom: zoom factor (default: 1.8) +""" +function set_axes_equal!(ax; zoom=1.8) + x_lims = ax.get_xlim3d() ./ zoom + y_lims = ax.get_ylim3d() ./ zoom + z_lims = ax.get_zlim3d() ./ zoom + + x_range = abs(x_lims[2] - x_lims[1]) + y_range = abs(y_lims[2] - y_lims[1]) + z_range = abs(z_lims[2] - z_lims[1]) + + max_range = max(x_range, y_range, z_range) + + x_mid = mean(x_lims) + y_mid = mean(y_lims) + z_mid = mean(z_lims) + + ax.set_xlim3d((x_mid - max_range / 2, x_mid + max_range / 2)) + ax.set_ylim3d((y_mid - max_range / 2, y_mid + max_range / 2)) + ax.set_zlim3d((z_mid - max_range / 2, z_mid + max_range / 2)) +end + +""" + create_geometry_plot(body_aero::BodyAerodynamics, title, view_elevation, view_azimuth; + zoom=1.8, use_tex=false) + +Create a 3D plot of wing geometry including panels and filaments. + +# Arguments +- body_aero: struct of type BodyAerodynamics +- title: plot title +- view_elevation: initial view elevation angle [°] +- view_azimuth: initial view azimuth angle [°] + +# Keyword arguments +- zoom: zoom factor (default: 1.8) +""" +function create_geometry_plot(body_aero::BodyAerodynamics, title, view_elevation, view_azimuth; + zoom=1.8, use_tex=false) + set_plot_style(28; use_tex) + + panels = body_aero.panels + va = isa(body_aero.va, Tuple) ? body_aero.va[1] : body_aero.va + + # Extract geometric data + corner_points = [panel.corner_points for panel in panels] + control_points = [panel.control_point for panel in panels] + aero_centers = [panel.aero_center for panel in panels] + + # Create plot + fig = plt.figure(figsize=(14, 14)) + ax = fig.add_subplot(111, projection="3d") + ax.set_title(title) + + # Plot panels + legend_used = Dict{String,Bool}() + for (i, panel) in enumerate(panels) + # Plot panel edges and surfaces + corners = Matrix{Float64}(panel.corner_points) + x_corners = corners[1, :] + y_corners = corners[2, :] + z_corners = corners[3, :] + + push!(x_corners, x_corners[1]) + push!(y_corners, y_corners[1]) + push!(z_corners, z_corners[1]) + + ax.plot(x_corners, + y_corners, + z_corners, + color=:grey, + linewidth=1, + label=i == 1 ? "Panel Edges" : "") + + # Plot control points and aerodynamic centers + ax.scatter([control_points[i][1]], [control_points[i][2]], [control_points[i][3]], + color=:green, label=i == 1 ? "Control Points" : "") + ax.scatter([aero_centers[i][1]], [aero_centers[i][2]], [aero_centers[i][3]], + color=:blue, label=i == 1 ? "Aerodynamic Centers" : "") + + # Plot filaments + filaments = calculate_filaments_for_plotting(panel) + legends = ["Bound Vortex", "side1", "side2", "wake_1", "wake_2"] + + for (filament, legend) in zip(filaments, legends) + x1, x2, color = filament + @debug "Legend: $legend" + show_legend = !get(legend_used, legend, false) + plot_line_segment!(ax, [x1, x2], color, show_legend ? legend : "") + legend_used[legend] = true + end + end + + # Plot velocity vector + max_chord = maximum(panel.chord for panel in panels) + va_mag = norm(va) + va_vector_begin = -2 * max_chord * va / va_mag + va_vector_end = va_vector_begin + 1.5 * va / va_mag + plot_line_segment!(ax, [va_vector_begin, va_vector_end], :lightblue, "va") + + # Add legends for the first occurrence of each label + handles, labels = ax.get_legend_handles_labels() + # by_label = Dict(zip(labels, handles)) + # ax.legend(values(by_label), keys(by_label), bbox_to_anchor=(0, 0, 1.1, 1)) + + # Set labels and make axes equal + ax.set_xlabel("x") + ax.set_ylabel("y") + ax.set_zlabel("z") + set_axes_equal!(ax; zoom) + + # Set the initial view + ax.view_init(elev=view_elevation, azim=view_azimuth) + + # Ensure the figure is fully rendered + # fig.canvas.draw() + plt.tight_layout(rect=(0, 0, 1, 0.97)) + + return fig +end + +""" + plot_geometry(body_aero::BodyAerodynamics, title; + data_type=".pdf", save_path=nothing, + is_save=false, is_show=false, + view_elevation=15, view_azimuth=-120, use_tex=false) + +Plot wing geometry from different viewpoints and optionally save/show plots. + +# Arguments: +- `body_aero`: the [BodyAerodynamics](@ref) to plot +- title: plot title + +# Keyword arguments: +- `data_type``: string with the file type postfix (default: ".pdf") +- `save_path`: path for saving the graphic (default: `nothing`) +- `is_save`: boolean value, indicates if the graphic shall be saved (default: `false`) +- `is_show`: boolean value, indicates if the graphic shall be displayed (default: `false`) +- `view_elevation`: initial view elevation angle (default: 15) [°] +- `view_azimuth`: initial view azimuth angle (default: -120) [°] +- `use_tex`: if the external `pdflatex` command shall be used (default: false) + +""" +function VortexStepMethod.plot_geometry(body_aero::BodyAerodynamics, title; + data_type=".pdf", + save_path=nothing, + is_save=false, + is_show=false, + view_elevation=15, + view_azimuth=-120, + use_tex=false) + + if is_save + plt.ioff() + # Angled view + fig = create_geometry_plot(body_aero, "$(title)_angled_view", 15, -120; use_tex) + save_plot(fig, save_path, "$(title)_angled_view", data_type=data_type) + + # Top view + fig = create_geometry_plot(body_aero, "$(title)_top_view", 90, 0; use_tex) + save_plot(fig, save_path, "$(title)_top_view", data_type=data_type) + + # Front view + fig = create_geometry_plot(body_aero, "$(title)_front_view", 0, 0; use_tex) + save_plot(fig, save_path, "$(title)_front_view", data_type=data_type) + + # Side view + fig = create_geometry_plot(body_aero, "$(title)_side_view", 0, -90; use_tex) + save_plot(fig, save_path, "$(title)_side_view", data_type=data_type) + end + + if is_show + plt.ion() + fig = create_geometry_plot(body_aero, title, view_elevation, view_azimuth; use_tex) + plt.display(fig) + else + fig = create_geometry_plot(body_aero, title, view_elevation, view_azimuth; use_tex) + end + fig +end + +""" + plot_distribution(y_coordinates_list, results_list, label_list; + title="spanwise_distribution", data_type=".pdf", + save_path=nothing, is_save=false, is_show=true, use_tex=false) + +Plot spanwise distributions of aerodynamic properties. + +# Arguments +- `y_coordinates_list`: List of spanwise coordinates +- `results_list`: List of result dictionaries +- `label_list`: List of labels for different results + +# Keyword arguments +- `title`: Plot title (default: "spanwise_distribution") +- `data_type`: File extension for saving (default: ".pdf") +- `save_path`: Path to save plots (default: nothing) +- `is_save`: Whether to save plots (default: false) +- `is_show`: Whether to display plots (default: true) +- `use_tex`: if the external `pdflatex` command shall be used +""" +function VortexStepMethod.plot_distribution(y_coordinates_list, results_list, label_list; + title="spanwise_distribution", + data_type=".pdf", + save_path=nothing, + is_save=false, + is_show=true, + use_tex=false) + + length(results_list) == length(label_list) || throw(ArgumentError( + "Number of results ($(length(results_list))) must match number of labels ($(length(label_list)))" + )) + + # Set the plot style + set_plot_style(; use_tex) + + # Initializing plot + fig, axs = plt.subplots(3, 3, figsize=(16, 10)) + fig.suptitle(title, fontsize=16) + + # CL plot + for (y_coordinates_i, result_i, label_i) in zip(y_coordinates_list, results_list, label_list) + value = "$(round(result_i["cl"], digits=2))" + if label_i == "LLT" + label = label_i * L" $~C_\mathrm{L}$: " * value + else + label = label_i * L" $C_\mathrm{L}$: " * value + end + axs[1, 1].plot( + y_coordinates_i, + result_i["cl_distribution"], + label=label + ) + end + axs[1, 1].set_title(L"$C_\mathrm{L}$ Distribution", size=16) + axs[1, 1].set_xlabel(L"Spanwise Position $y/b$") + axs[1, 1].set_ylabel(L"Lift Coefficient $C_\mathrm{L}$") + axs[1, 1].legend() + + # CD plot + for (y_coordinates_i, result_i, label_i) in zip(y_coordinates_list, results_list, label_list) + value = "$(round(result_i["cl"], digits=2))" + if label_i == "LLT" + label = label_i * L" $~C_\mathrm{D}$: " * value + else + label = label_i * L" $C_\mathrm{D}$: " * value + end + axs[1, 2].plot( + y_coordinates_i, + result_i["cd_distribution"], + label=label + ) + end + axs[1, 2].set_title(L"$C_\mathrm{D}$ Distribution", size=16) + axs[1, 2].set_xlabel(L"Spanwise Position $y/b$") + axs[1, 2].set_ylabel(L"Drag Coefficient $C_\mathrm{D}$") + axs[1, 2].legend() + + # Gamma Distribution + for (y_coordinates_i, result_i, label_i) in zip(y_coordinates_list, results_list, label_list) + axs[1, 3].plot( + y_coordinates_i, + result_i["gamma_distribution"], + label=label_i + ) + end + axs[1, 3].set_title(L"\Gamma~Distribution", size=16) + axs[1, 3].set_xlabel(L"Spanwise Position $y/b$") + axs[1, 3].set_ylabel(L"Circulation~\Gamma") + axs[1, 3].legend() + + # Geometric Alpha + for (y_coordinates_i, result_i, label_i) in zip(y_coordinates_list, results_list, label_list) + axs[2, 1].plot( + y_coordinates_i, + result_i["alpha_geometric"], + label=label_i + ) + end + axs[2, 1].set_title(L"$\alpha$ Geometric", size=16) + axs[2, 1].set_xlabel(L"Spanwise Position $y/b$") + axs[2, 1].set_ylabel(L"Angle of Attack $\alpha$ (deg)") + axs[2, 1].legend() + + # Calculated/ Corrected Alpha + for (y_coordinates_i, result_i, label_i) in zip(y_coordinates_list, results_list, label_list) + axs[2, 2].plot( + y_coordinates_i, + result_i["alpha_at_ac"], + label=label_i + ) + end + axs[2, 2].set_title(L"$\alpha$ result (corrected to aerodynamic center)", size=16) + axs[2, 2].set_xlabel(L"Spanwise Position $y/b$") + axs[2, 2].set_ylabel(L"Angle of Attack $\alpha$ (deg)") + axs[2, 2].legend() + + # Uncorrected Alpha plot + for (y_coordinates_i, result_i, label_i) in zip(y_coordinates_list, results_list, label_list) + axs[2, 3].plot( + y_coordinates_i, + result_i["alpha_uncorrected"], + label=label_i + ) + end + axs[2, 3].set_title(L"$\alpha$ Uncorrected (if VSM, at the control point)", size=16) + axs[2, 3].set_xlabel(L"Spanwise Position $y/b$") + axs[2, 3].set_ylabel(L"Angle of Attack $\alpha$ (deg)") + axs[2, 3].legend() + + # Force Components + for (idx, component) in enumerate(["x", "y", "z"]) + axs[3, idx].set_title("Force in $component direction", size=16) + axs[3, idx].set_xlabel(L"Spanwise Position $y/b$") + axs[3, idx].set_ylabel(raw"$F_\mathrm" * "{$component}" * raw"$") + for (y_coords, results, label) in zip(y_coordinates_list, results_list, label_list) + # Extract force components for the current direction (idx) + forces = results["F_distribution"][idx, :] + # Verify dimensions match + if length(y_coords) != length(forces) + @warn "Dimension mismatch in force plotting" length(y_coords) length(forces) component + continue # Skip this component instead of throwing error + end + space = "" + if label == "LLT" + space = "~" + end + axs[3, idx].plot( + y_coords, + forces, + label="$label" * space * raw"$~\Sigma~F_\mathrm" * "{$component}:~" * + raw"$" * "$(round(results["F$component"], digits=2)) N" + ) + axs[3, idx].legend() + end + end + + fig.tight_layout() + + # Save and show plot + if is_save + save_plot(fig, save_path, title, data_type=data_type) + end + + if is_show + show_plot(fig) + end + + return fig +end + +""" + generate_polar_data(solver, body_aero::BodyAerodynamics, angle_range; + angle_type="angle_of_attack", angle_of_attack=0.0, + side_slip=0.0, v_a=10.0, use_latex=false) + +Generate polar data for aerodynamic analysis over a range of angles. + +# Arguments +- `solver`: Aerodynamic solver object +- `body_aero`: Wing aerodynamics struct +- `angle_range`: Range of angles to analyze + +# Keyword arguments +- `angle_type`: Type of angle variation ("angle_of_attack" or "side_slip") +- `angle_of_attack`: Initial angle of attack [rad] +- `side_slip`: Initial side slip angle in [rad] +- `v_a`: norm of apparent wind speed [m/s] + +# Returns +- Tuple of polar data array and Reynolds number +""" +function generate_polar_data( + solver, + body_aero::BodyAerodynamics, + angle_range; + angle_type="angle_of_attack", + angle_of_attack=0.0, + side_slip=0.0, + v_a=10.0, + use_latex=false +) + n_panels = length(body_aero.panels) + n_angles = length(angle_range) + + # Initialize arrays + cl = zeros(n_angles) + cd = zeros(n_angles) + cs = zeros(n_angles) + gamma_distribution = zeros(n_angles, n_panels) + cl_distribution = zeros(n_angles, n_panels) + cd_distribution = zeros(n_angles, n_panels) + cs_distribution = zeros(n_angles, n_panels) + reynolds_number = zeros(n_angles) + + # Previous gamma for initialization + gamma = nothing + + for (i, angle_i) in enumerate(angle_range) + # Set angle based on type + if angle_type == "angle_of_attack" + α = deg2rad(angle_i) + β = side_slip + elseif angle_type == raw"side_slip" + α = angle_of_attack + β = deg2rad(angle_i) + else + throw(ArgumentError("angle_type must be 'angle_of_attack' or 'side_slip'")) + end + + # Update inflow conditions + set_va!( + body_aero, + [ + cos(α) * cos(β), + sin(β), + sin(α) + ] * v_a + ) + + # Solve and store results + results = solve(solver, body_aero, gamma_distribution[i, :]) + + cl[i] = results["cl"] + cd[i] = results["cd"] + cs[i] = results["cs"] + gamma_distribution[i, :] = results["gamma_distribution"] + cl_distribution[i, :] = results["cl_distribution"] + cd_distribution[i, :] = results["cd_distribution"] + cs_distribution[i, :] = results["cs_distribution"] + reynolds_number[i] = results["Rey"] + + # Store gamma for next iteration + gamma = gamma_distribution[i, :] + end + + polar_data = [ + angle_range, + cl, + cd, + cs, + gamma_distribution, + cl_distribution, + cd_distribution, + cs_distribution, + reynolds_number + ] + + return polar_data, reynolds_number[1] +end + +""" + plot_polars(solver_list, body_aero_list, label_list; + literature_path_list=String[], + angle_range=range(0, 20, 2), angle_type="angle_of_attack", + angle_of_attack=0.0, side_slip=0.0, v_a=10.0, + title="polar", data_type=".pdf", save_path=nothing, + is_save=true, is_show=true, use_tex=false) + +Plot polar data comparing different solvers and configurations. + +# Arguments +- `solver_list`: List of aerodynamic solvers +- `body_aero_list`: List of wing aerodynamics objects +- `label_list`: List of labels for each configuration + +# Keyword arguments +- `literature_path_list`: Optional paths to literature data files +- `angle_range`: Range of angles to analyze [°] +- `angle_type`: "`angle_of_attack`" or "`side_slip`"; (default: `angle_of_attack`) +- `angle_of_attack:` AoA to be used for plotting the polars (default: 0.0) [rad] +- `side_slip`: side slip angle (default: 0.0) [rad] +- v_a: norm of apparent wind speed (default: 10.0) [m/s] +- title: plot title +- `data_type`: File extension for saving (default: ".pdf") +- `save_path`: Path to save plots (default: nothing) +- `is_save`: Whether to save plots (default: true) +- `is_show`: Whether to display plots (default: true) +- `use_tex`: if the external `pdflatex` command shall be used (default: false) +""" +function VortexStepMethod.plot_polars( + solver_list, + body_aero_list, + label_list; + literature_path_list=String[], + angle_range=range(0, 20, 2), + angle_type="angle_of_attack", + angle_of_attack=0.0, + side_slip=0.0, + v_a=10.0, + title="polar", + data_type=".pdf", + save_path=nothing, + is_save=true, + is_show=true, + use_tex=false +) + # Validate inputs + total_cases = length(body_aero_list) + length(literature_path_list) + if total_cases != length(label_list) || length(solver_list) != length(body_aero_list) + throw(ArgumentError("Mismatch in number of solvers ($(length(solver_list))), " * + "cases ($total_cases), and labels ($(length(label_list)))")) + end + main_title = replace(title, " " => "_") + set_plot_style(; use_tex) + + # Generate polar data + polar_data_list = [] + for (i, (solver, body_aero)) in enumerate(zip(solver_list, body_aero_list)) + polar_data, rey = generate_polar_data( + solver, body_aero, angle_range; + angle_type, + angle_of_attack, + side_slip, + v_a + ) + push!(polar_data_list, polar_data) + # Update label with Reynolds number + label_list[i] = "$(label_list[i]) Re = $(round(Int64, rey*1e-5))e5" + end + # Load literature data if provided + if !isempty(literature_path_list) + for path in literature_path_list + data = readdlm(path, ',') + header = lowercase.(string.(data[1, :])) + # Find column indices for alpha, CL, CD, CS (case-insensitive, allow common variants) + alpha_idx = findfirst(x -> occursin("alpha", x), header) + cl_idx = findfirst(x -> occursin("cl", x), header) + cd_idx = findfirst(x -> occursin("cd", x), header) + cs_idx = findfirst(x -> occursin("cs", x), header) + # Fallback: if CS not found, fill with zeros + cs_col = cs_idx === nothing ? zeros(size(data, 1)-1) : data[2:end, cs_idx] + # Push as [alpha, CL, CD, CS] + push!(polar_data_list, [ + data[2:end, alpha_idx], + data[2:end, cl_idx], + data[2:end, cd_idx], + cs_col + ]) + end + end + + # Initializing plot + fig, axs = plt.subplots(2, 2, figsize=(14, 14)) + + # Number of computational results (excluding literature) + n_solvers = length(solver_list) + for (i, (polar_data, label)) in enumerate(zip(polar_data_list, label_list)) + if i < n_solvers + linestyle = "-" + marker = "*" + markersize = 7 + else + linestyle = "-" + marker = "." + markersize = 5 + end + if contains(label, "LLT") + label = replace(label, "e5" => raw"\cdot10^5") + label = replace(label, " " => raw"~") + label = replace(label, "LLT" => raw"\mathrm{LLT}{~\,}") + label = raw"$" * label * raw"$" + else + label = replace(label, "e5" => raw"\cdot10^5") + label = replace(label, " " => "~") + label = replace(label, "VSM" => raw"\mathrm{VSM}") + label = raw"$" * label * raw"$" + end + axs[1, 1].plot( + polar_data[1], + polar_data[2], + label=label, + linestyle=linestyle, + marker=marker, + markersize=markersize, + ) + # Limit y-range if CL > 10 + if maximum(polar_data[2]) > 10 + axs[1, 1].set_ylim([-0.5, 2]) + end + title = raw"$C_\mathrm{L}" * raw"$" * " vs $angle_type [°]" + axs[1, 1].set_title(title) + axs[1, 1].set_xlabel("$angle_type [°]") + axs[1, 1].set_ylabel(L"$C_\mathrm{L}$") + axs[1, 1].legend() + end + + for (i, (polar_data, label)) in enumerate(zip(polar_data_list, label_list)) + if i < n_solvers + linestyle = "-" + marker = "*" + markersize = 7 + else + linestyle = "-" + marker = "." + markersize = 5 + end + if contains(label, "LLT") + label = replace(label, "e5" => raw"\cdot10^5") + label = replace(label, " " => raw"~") + label = replace(label, "LLT" => raw"\mathrm{LLT}{~\,}") + label = raw"$" * label * raw"$" + else + label = replace(label, "e5" => raw"\cdot10^5") + label = replace(label, " " => "~") + label = replace(label, "VSM" => raw"\mathrm{VSM}") + label = raw"$" * label * raw"$" + end + axs[1, 2].plot( + polar_data[1], + polar_data[3], + label=label, + linestyle=linestyle, + marker=marker, + markersize=markersize, + ) + # Limit y-range if CL > 10 + if maximum(polar_data[2]) > 10 + axs[1, 2].set_ylim([-0.5, 2]) + end + title = raw"$C_\mathrm{D}" * raw"$" * " vs $angle_type [°]" + axs[1, 2].set_title(title) + axs[1, 2].set_xlabel("$angle_type [°]") + axs[1, 2].set_ylabel(L"$C_\mathrm{D}$") + axs[1, 2].legend() + end + + + for (i, (polar_data, label)) in enumerate(zip(polar_data_list, label_list)) + if i < n_solvers + linestyle = "-" + marker = "*" + markersize = 7 + else + linestyle = "-" + marker = "." + markersize = 5 + end + if contains(label, "LLT") + label = replace(label, "e5" => raw"\cdot10^5") + label = replace(label, " " => raw"~") + label = replace(label, "LLT" => raw"\mathrm{LLT}{~\,}") + label = raw"$" * label * raw"$" + else + label = replace(label, "e5" => raw"\cdot10^5") + label = replace(label, " " => "~") + label = replace(label, "VSM" => raw"\mathrm{VSM}") + label = raw"$" * label * raw"$" + end + axs[2, 1].plot( + polar_data[1], + polar_data[4], + label=label, + linestyle=linestyle, + marker=marker, + markersize=markersize, + ) + # Limit y-range if CL > 10 + if maximum(polar_data[2]) > 10 + axs[2, 1].set_ylim([-0.5, 2]) + end + title = raw"$C_\mathrm{S}" * raw"$" * " vs $angle_type [°]" + axs[2, 1].set_title(title) + axs[2, 1].set_xlabel("$angle_type [°]") + axs[2, 1].set_ylabel(L"$C_\mathrm{S}$") + axs[2, 1].legend() + end + + for (i, (polar_data, label)) in enumerate(zip(polar_data_list, label_list)) + if i < n_solvers + linestyle = "-" + marker = "*" + markersize = 7 + else + linestyle = "-" + marker = "." + markersize = 5 + end + if contains(label, "LLT") + label = replace(label, "e5" => raw"\cdot10^5") + label = replace(label, " " => raw"~") + label = replace(label, "LLT" => raw"\mathrm{LLT}{~\,}") + label = raw"$" * label * raw"$" + else + label = replace(label, "e5" => raw"\cdot10^5") + label = replace(label, " " => "~") + label = replace(label, "VSM" => raw"\mathrm{VSM}") + label = raw"$" * label * raw"$" + end + axs[2, 2].plot( + polar_data[3], + polar_data[2], + label=label, + linestyle=linestyle, + marker=marker, + markersize=markersize, + ) + # Limit y-range if CL > 10 + if maximum(polar_data[2]) > 10 || maximum(polar_data[3]) > 10 + axs[2, 2].set_ylim([-0.5, 2]) + axs[2, 2].set_xlim([-0.5, 2]) + end + title = raw"$C_\mathrm{L}" * raw"$" * " vs " * raw"$C_\mathrm{D}" * raw"$" + axs[2, 2].set_title(title) + axs[2, 2].set_xlabel(L"$C_\mathrm{D}$") + axs[2, 2].set_ylabel(L"$C_\mathrm{L}$") + axs[2, 2].legend() + end + + fig.tight_layout(h_pad=3.5, rect=(0.01, 0.01, 0.99, 0.99)) + + # Save and show plot + if is_save && !isnothing(save_path) + save_plot(fig, save_path, main_title; data_type) + end + + if is_show + show_plot(fig) + end + + return fig +end + +""" + plot_polar_data(body_aero::BodyAerodynamics; alphas=collect(deg2rad.(-5:0.3:25)), delta_tes=collect(deg2rad.(-5:0.3:25))) + +Plot polar data (Cl, Cd, Cm) as 3D surfaces against alpha and delta_te angles. delta_te is the trailing edge deflection angle +relative to the 2d airfoil or panel chord line. + +# Arguments +- `body_aero`: Wing aerodynamics struct + +# Keyword arguments +- `alphas`: Range of angle of attack values in radians (default: -5° to 25° in 0.3° steps) +- `delta_tes`: Range of trailing edge angles in radians (default: -5° to 25° in 0.3° steps) +- `is_show`: Whether to display plots (default: true) +- `use_tex`: if the external `pdflatex` command shall be used +""" +function VortexStepMethod.plot_polar_data(body_aero::BodyAerodynamics; + alphas=collect(deg2rad.(-5:0.3:25)), + delta_tes = collect(deg2rad.(-5:0.3:25)), + is_show = true, + use_tex = false + ) + if body_aero.panels[1].aero_model == POLAR_MATRICES + set_plot_style() + + # Create figure with subplots + fig = plt.figure(figsize=(15, 6)) + + # Get interpolation functions and labels + interp_data = [ + (body_aero.panels[1].cl_interp, L"$C_l$"), + (body_aero.panels[1].cd_interp, L"$C_d$"), + (body_aero.panels[1].cm_interp, L"$C_m$") + ] + + # Create each subplot + for (idx, (interp, label)) in enumerate(interp_data) + ax = fig.add_subplot(1, 3, idx, projection="3d") + + # Create interpolation matrix + interp_matrix = zeros(length(alphas), length(delta_tes)) + interp_matrix .= [interp(alpha, delta_te) for alpha in alphas, delta_te in delta_tes] + X = collect(delta_tes) .+ zeros(length(alphas))' + Y = collect(alphas)' .+ zeros(length(delta_tes)) + + # Plot surface + ax.plot_wireframe(X, Y, interp_matrix, + edgecolor="blue", + lw=0.5, + rstride=5, + cstride=5, + alpha=0.6) + + # Set labels and title + ax.set_xlabel(L"$\delta$ [rad]") + ax.set_ylabel(L"$\alpha$ [rad]") + ax.set_zlabel(label) + ax.set_title(label * L" vs $\alpha$ and $\delta$") + ax.grid(true) + end + + # Adjust layout and display + plt.tight_layout(rect=(0.01, 0.01, 0.99, 0.99)) + if is_show + show_plot(fig) + end + return fig + else + throw(ArgumentError("Plotting polar data for $(body_aero.panels[1].aero_model) is not implemented.")) + end +end end \ No newline at end of file diff --git a/ext/VortexStepMethodMakieExt.jl b/ext/VortexStepMethodMakieExt.jl index f72ea3d8..69819d2a 100644 --- a/ext/VortexStepMethodMakieExt.jl +++ b/ext/VortexStepMethodMakieExt.jl @@ -1,5 +1,8 @@ module VortexStepMethodMakieExt -using Makie, VortexStepMethod +using Makie, VortexStepMethod, LinearAlgebra, Statistics, DelimitedFiles +import VortexStepMethod: calculate_filaments_for_plotting + +export plot_geometry, plot_distribution, plot_polars, save_plot, show_plot, plot_polar_data """ plot!(ax, panel::VortexStepMethod.Panel; kwargs...) @@ -62,4 +65,689 @@ function Makie.plot(body_aero::VortexStepMethod.BodyAerodynamics; size = (1200, return fig end +""" + save_plot(fig, save_path, title; data_type=".pdf") + +Save a Makie figure to a file. + +# Arguments +- `fig`: Makie Figure object +- `save_path`: Path to save the plot +- `title`: Title of the plot + +# Keyword arguments +- `data_type`: File extension (default: ".pdf") +""" +function VortexStepMethod.save_plot(fig, save_path, title; data_type=".pdf") + isnothing(save_path) && throw(ArgumentError("save_path should be provided")) + + !isdir(save_path) && mkpath(save_path) + full_path = joinpath(save_path, title * data_type) + + @debug "Attempting to save figure to: $full_path" + @debug "Current working directory: $(pwd())" + + try + save(full_path, fig) + @debug "Figure saved as $data_type" + + if isfile(full_path) + @debug "File successfully saved to $full_path" + @debug "File size: $(filesize(full_path)) bytes" + else + @info "File does not exist after save attempt: $full_path" + end + catch e + @error "Error saving figure: $e" + @error "Error type: $(typeof(e))" + rethrow(e) + end +end + +""" + show_plot(fig; dpi=130) + +Display a Makie figure. + +# Arguments +- `fig`: Makie Figure object + +# Keyword arguments +- `dpi`: Dots per inch for the figure (default: 130) - currently unused in Makie +""" +function VortexStepMethod.show_plot(fig; dpi=130) + display(fig) +end + +""" + plot_line_segment_makie!(ax, segment, color, label; width=3) + +Plot a line segment in 3D with arrow using Makie. + +# Arguments +- `ax`: Makie Axis3 +- `segment`: Array of two points defining the segment +- `color`: Color of the segment +- `label`: Label for the legend + +# Keyword Arguments +- `width`: Line width (default: 3) +""" +function plot_line_segment_makie!(ax, segment, color, label; width=3) + # Plot line + lines!(ax, [Point3f(segment[1]), Point3f(segment[2])]; + color=color, linewidth=width, label=label) + + # Plot arrow + dir = segment[2] - segment[1] + arrows!(ax, [Point3f(segment[1])], [Point3f(dir)]; + color=color, arrowsize=0.1) +end + +""" + set_axes_equal_makie!(ax, panels; zoom=1.8) + +Set 3D Makie axis to equal scale based on panel data. + +# Arguments +- `ax`: Makie Axis3 +- `panels`: Array of panels +- `zoom`: zoom factor (default: 1.8) +""" +function set_axes_equal_makie!(ax, panels; zoom=1.8) + # Calculate bounds from all panels + all_x = Float64[] + all_y = Float64[] + all_z = Float64[] + + for panel in panels + for i in 1:4 + push!(all_x, panel.corner_points[1, i]) + push!(all_y, panel.corner_points[2, i]) + push!(all_z, panel.corner_points[3, i]) + end + end + + x_range = (maximum(all_x) - minimum(all_x)) / zoom + y_range = (maximum(all_y) - minimum(all_y)) / zoom + z_range = (maximum(all_z) - minimum(all_z)) / zoom + + max_range = max(x_range, y_range, z_range) + + x_mid = mean([maximum(all_x), minimum(all_x)]) + y_mid = mean([maximum(all_y), minimum(all_y)]) + z_mid = mean([maximum(all_z), minimum(all_z)]) + + limits!(ax, + x_mid - max_range/2, x_mid + max_range/2, + y_mid - max_range/2, y_mid + max_range/2, + z_mid - max_range/2, z_mid + max_range/2) +end + +""" + create_geometry_plot_makie(body_aero::BodyAerodynamics, title, + view_elevation, view_azimuth; zoom=1.8) + +Create a 3D Makie plot of wing geometry including panels and filaments. + +# Arguments +- `body_aero`: struct of type BodyAerodynamics +- `title`: plot title +- `view_elevation`: initial view elevation angle [°] +- `view_azimuth`: initial view azimuth angle [°] + +# Keyword arguments +- `zoom`: zoom factor (default: 1.8) +""" +function create_geometry_plot_makie(body_aero::BodyAerodynamics, title, + view_elevation, view_azimuth; zoom=1.8) + panels = body_aero.panels + va = isa(body_aero.va, Tuple) ? body_aero.va[1] : body_aero.va + + # Create figure + fig = Figure(size=(1400, 1400)) + ax = Axis3(fig[1, 1]; + title=title, + xlabel="x", ylabel="y", zlabel="z", + aspect=:data, + azimuth=deg2rad(view_azimuth), + elevation=deg2rad(view_elevation)) + + # Plot panels + legend_used = Dict{String,Bool}() + for (i, panel) in enumerate(panels) + # Panel edges + corners = [Point3f(panel.corner_points[:, j]) for j in 1:4] + push!(corners, corners[1]) + lines!(ax, corners; color=:grey, linewidth=1, + label = i == 1 ? "Panel Edges" : nothing) + + # Control points + scatter!(ax, [Point3f(panel.control_point)]; + color=:green, markersize=10, + label = i == 1 ? "Control Points" : nothing) + + # Aerodynamic centers + scatter!(ax, [Point3f(panel.aero_center)]; + color=:blue, markersize=10, + label = i == 1 ? "Aerodynamic Centers" : nothing) + + # Plot filaments + filaments = calculate_filaments_for_plotting(panel) + legends = ["Bound Vortex", "side1", "side2", "wake_1", "wake_2"] + + for (filament, legend) in zip(filaments, legends) + x1, x2, color = filament + show_legend = !get(legend_used, legend, false) + plot_line_segment_makie!(ax, [x1, x2], color, + show_legend ? legend : nothing) + legend_used[legend] = true + end + end + + # Plot velocity vector + max_chord = maximum(panel.chord for panel in panels) + va_mag = norm(va) + va_vector_begin = -2 * max_chord * va / va_mag + va_vector_end = va_vector_begin + 1.5 * va / va_mag + plot_line_segment_makie!(ax, [va_vector_begin, va_vector_end], :lightblue, "va") + + # Set equal axes + set_axes_equal_makie!(ax, panels; zoom) + + # Add legend + axislegend(ax; position=:lt) + + return fig +end + +""" + plot_geometry(body_aero::BodyAerodynamics, title; + data_type=".pdf", save_path=nothing, + is_save=false, is_show=false, + view_elevation=15, view_azimuth=-120, use_tex=false) + +Plot wing geometry from different viewpoints using Makie. + +# Arguments: +- `body_aero`: the BodyAerodynamics to plot +- `title`: plot title + +# Keyword arguments: +- `data_type`: File extension (default: ".pdf") +- `save_path`: Path for saving (default: nothing) +- `is_save`: Whether to save (default: false) +- `is_show`: Whether to display (default: false) +- `view_elevation`: View elevation angle [°] (default: 15) +- `view_azimuth`: View azimuth angle [°] (default: -120) +- `use_tex`: Ignored for Makie (default: false) +""" +function VortexStepMethod.plot_geometry(body_aero::BodyAerodynamics, title; + data_type=".pdf", + save_path=nothing, + is_save=false, + is_show=false, + view_elevation=15, + view_azimuth=-120, + use_tex=false) + + if is_save + # Angled view + fig = create_geometry_plot_makie(body_aero, "$(title)_angled_view", 15, -120) + save_plot(fig, save_path, "$(title)_angled_view", data_type=data_type) + + # Top view + fig = create_geometry_plot_makie(body_aero, "$(title)_top_view", 90, 0) + save_plot(fig, save_path, "$(title)_top_view", data_type=data_type) + + # Front view + fig = create_geometry_plot_makie(body_aero, "$(title)_front_view", 0, 0) + save_plot(fig, save_path, "$(title)_front_view", data_type=data_type) + + # Side view + fig = create_geometry_plot_makie(body_aero, "$(title)_side_view", 0, -90) + save_plot(fig, save_path, "$(title)_side_view", data_type=data_type) + end + + fig = create_geometry_plot_makie(body_aero, title, view_elevation, view_azimuth) + + if is_show + display(fig) + end + + return fig +end + +""" + plot_distribution(y_coordinates_list, results_list, label_list; + title="spanwise_distribution", data_type=".pdf", + save_path=nothing, is_save=false, is_show=true, use_tex=false) + +Plot spanwise distributions of aerodynamic properties using Makie. + +# Arguments +- `y_coordinates_list`: List of spanwise coordinates +- `results_list`: List of result dictionaries +- `label_list`: List of labels for different results + +# Keyword arguments +- `title`: Plot title (default: "spanwise_distribution") +- `data_type`: File extension (default: ".pdf") +- `save_path`: Path to save plots (default: nothing) +- `is_save`: Whether to save (default: false) +- `is_show`: Whether to display (default: true) +- `use_tex`: Ignored for Makie (default: false) +""" +function VortexStepMethod.plot_distribution(y_coordinates_list, results_list, label_list; + title="spanwise_distribution", + data_type=".pdf", + save_path=nothing, + is_save=false, + is_show=true, + use_tex=false) + + length(results_list) == length(label_list) || throw(ArgumentError( + "Number of results ($(length(results_list))) must match labels ($(length(label_list)))" + )) + + # Create figure with 3x3 grid + fig = Figure(size=(1600, 1000)) + Label(fig[0, :], title, fontsize=20) + + # Row 1: CL, CD, Gamma + ax_cl = Axis(fig[1, 1], title="CL Distribution", + xlabel="Spanwise Position y/b", ylabel="Lift Coefficient CL") + ax_cd = Axis(fig[1, 2], title="CD Distribution", + xlabel="Spanwise Position y/b", ylabel="Drag Coefficient CD") + ax_gamma = Axis(fig[1, 3], title="Γ Distribution", + xlabel="Spanwise Position y/b", ylabel="Circulation Γ") + + # Row 2: Alpha geometric, alpha at ac, alpha uncorrected + ax_alpha_geo = Axis(fig[2, 1], title="α Geometric", + xlabel="Spanwise Position y/b", ylabel="Angle of Attack α (deg)") + ax_alpha_ac = Axis(fig[2, 2], title="α result (corrected to aerodynamic center)", + xlabel="Spanwise Position y/b", ylabel="Angle of Attack α (deg)") + ax_alpha_unc = Axis(fig[2, 3], title="α Uncorrected (if VSM, at control point)", + xlabel="Spanwise Position y/b", ylabel="Angle of Attack α (deg)") + + # Row 3: Force components + ax_fx = Axis(fig[3, 1], title="Force in x direction", + xlabel="Spanwise Position y/b", ylabel="Fx") + ax_fy = Axis(fig[3, 2], title="Force in y direction", + xlabel="Spanwise Position y/b", ylabel="Fy") + ax_fz = Axis(fig[3, 3], title="Force in z direction", + xlabel="Spanwise Position y/b", ylabel="Fz") + + # Plot CL + for (y_coords, results, label) in zip(y_coordinates_list, results_list, label_list) + value = round(results["cl"], digits=2) + lines!(ax_cl, Vector(y_coords), Vector(results["cl_distribution"]), + label="$label CL: $value") + end + axislegend(ax_cl, position=:lt) + + # Plot CD + for (y_coords, results, label) in zip(y_coordinates_list, results_list, label_list) + value = round(results["cd"], digits=2) + lines!(ax_cd, Vector(y_coords), Vector(results["cd_distribution"]), + label="$label CD: $value") + end + axislegend(ax_cd, position=:lt) + + # Plot Gamma + for (y_coords, results, label) in zip(y_coordinates_list, results_list, label_list) + lines!(ax_gamma, Vector(y_coords), Vector(results["gamma_distribution"]), + label=label) + end + axislegend(ax_gamma, position=:lt) + + # Plot alpha geometric + for (y_coords, results, label) in zip(y_coordinates_list, results_list, label_list) + lines!(ax_alpha_geo, Vector(y_coords), Vector(results["alpha_geometric"]), + label=label) + end + axislegend(ax_alpha_geo, position=:lt) + + # Plot alpha at ac + for (y_coords, results, label) in zip(y_coordinates_list, results_list, label_list) + lines!(ax_alpha_ac, Vector(y_coords), Vector(results["alpha_at_ac"]), + label=label) + end + axislegend(ax_alpha_ac, position=:lt) + + # Plot alpha uncorrected + for (y_coords, results, label) in zip(y_coordinates_list, results_list, label_list) + lines!(ax_alpha_unc, Vector(y_coords), Vector(results["alpha_uncorrected"]), + label=label) + end + axislegend(ax_alpha_unc, position=:lt) + + # Plot force components + force_axes = [ax_fx, ax_fy, ax_fz] + components = ["x", "y", "z"] + for (idx, (ax, comp)) in enumerate(zip(force_axes, components)) + for (y_coords, results, label) in zip(y_coordinates_list, results_list, label_list) + forces = results["F_distribution"][idx, :] + if length(y_coords) != length(forces) + @warn "Dimension mismatch" length(y_coords) length(forces) comp + continue + end + total_force = round(results["F$comp"], digits=2) + lines!(ax, Vector(y_coords), Vector(forces), + label="$label ΣF$comp: $total_force N") + end + axislegend(ax, position=:lt) + end + + # Save and show + if is_save + save_plot(fig, save_path, title, data_type=data_type) + end + + if is_show + display(fig) + end + + return fig +end + +""" + generate_polar_data(solver, body_aero::BodyAerodynamics, angle_range; + angle_type="angle_of_attack", angle_of_attack=0.0, + side_slip=0.0, v_a=10.0) + +Generate polar data for aerodynamic analysis over a range of angles. + +# Arguments +- `solver`: Aerodynamic solver object +- `body_aero`: Wing aerodynamics struct +- `angle_range`: Range of angles to analyze + +# Keyword arguments +- `angle_type`: Type of angle variation ("angle_of_attack" or "side_slip") +- `angle_of_attack`: Initial angle of attack [rad] +- `side_slip`: Initial side slip angle [rad] +- `v_a`: norm of apparent wind speed [m/s] + +# Returns +- Tuple of polar data array and Reynolds number +""" +function generate_polar_data_makie( + solver, + body_aero::BodyAerodynamics, + angle_range; + angle_type="angle_of_attack", + angle_of_attack=0.0, + side_slip=0.0, + v_a=10.0 +) + n_panels = length(body_aero.panels) + n_angles = length(angle_range) + + # Initialize arrays + cl = zeros(n_angles) + cd = zeros(n_angles) + cs = zeros(n_angles) + gamma_distribution = zeros(n_angles, n_panels) + reynolds_number = zeros(n_angles) + + for (i, angle_i) in enumerate(angle_range) + # Set angle based on type + if angle_type == "angle_of_attack" + α = deg2rad(angle_i) + β = side_slip + elseif angle_type == "side_slip" + α = angle_of_attack + β = deg2rad(angle_i) + else + throw(ArgumentError("angle_type must be 'angle_of_attack' or 'side_slip'")) + end + + # Update inflow conditions + set_va!( + body_aero, + [ + cos(α) * cos(β), + sin(β), + sin(α) + ] * v_a + ) + + # Solve and store results + results = solve(solver, body_aero, gamma_distribution[i, :]) + + cl[i] = results["cl"] + cd[i] = results["cd"] + cs[i] = results["cs"] + gamma_distribution[i, :] = results["gamma_distribution"] + reynolds_number[i] = results["Rey"] + end + + polar_data = [angle_range, cl, cd, cs] + return polar_data, reynolds_number[1] +end + +""" + plot_polars(solver_list, body_aero_list, label_list; + literature_path_list=String[], + angle_range=range(0, 20, 2), angle_type="angle_of_attack", + angle_of_attack=0.0, side_slip=0.0, v_a=10.0, + title="polar", data_type=".pdf", save_path=nothing, + is_save=true, is_show=true, use_tex=false) + +Plot polar data comparing different solvers using Makie. + +# Arguments +- `solver_list`: List of aerodynamic solvers +- `body_aero_list`: List of wing aerodynamics objects +- `label_list`: List of labels for each configuration + +# Keyword arguments +- `literature_path_list`: Optional paths to literature data files +- `angle_range`: Range of angles [°] +- `angle_type`: "angle_of_attack" or "side_slip" (default: angle_of_attack) +- `angle_of_attack`: AoA [rad] (default: 0.0) +- `side_slip`: Side slip angle [rad] (default: 0.0) +- `v_a`: Wind speed [m/s] (default: 10.0) +- `title`: Plot title +- `data_type`: File extension (default: ".pdf") +- `save_path`: Path to save (default: nothing) +- `is_save`: Whether to save (default: true) +- `is_show`: Whether to display (default: true) +- `use_tex`: Ignored for Makie (default: false) +""" +function VortexStepMethod.plot_polars( + solver_list, + body_aero_list, + label_list; + literature_path_list=String[], + angle_range=range(0, 20, 2), + angle_type="angle_of_attack", + angle_of_attack=0.0, + side_slip=0.0, + v_a=10.0, + title="polar", + data_type=".pdf", + save_path=nothing, + is_save=true, + is_show=true, + use_tex=false +) + # Validate inputs + total_cases = length(body_aero_list) + length(literature_path_list) + if total_cases != length(label_list) || length(solver_list) != length(body_aero_list) + throw(ArgumentError("Mismatch in solvers/cases/labels")) + end + main_title = replace(title, " " => "_") + + # Generate polar data + polar_data_list = [] + labels_with_re = copy(label_list) + for (i, (solver, body_aero)) in enumerate(zip(solver_list, body_aero_list)) + polar_data, rey = generate_polar_data_makie( + solver, body_aero, angle_range; + angle_type, angle_of_attack, side_slip, v_a + ) + push!(polar_data_list, polar_data) + labels_with_re[i] = "$(label_list[i]) Re = $(round(Int64, rey*1e-5))e5" + end + + # Load literature data if provided + if !isempty(literature_path_list) + for path in literature_path_list + data = readdlm(path, ',') + header = lowercase.(string.(data[1, :])) + alpha_idx = findfirst(x -> occursin("alpha", x), header) + cl_idx = findfirst(x -> occursin("cl", x), header) + cd_idx = findfirst(x -> occursin("cd", x), header) + cs_idx = findfirst(x -> occursin("cs", x), header) + cs_col = cs_idx === nothing ? zeros(size(data, 1)-1) : data[2:end, cs_idx] + push!(polar_data_list, [ + data[2:end, alpha_idx], + data[2:end, cl_idx], + data[2:end, cd_idx], + cs_col + ]) + end + end + + # Create figure with 2x2 grid + fig = Figure(size=(1400, 1400)) + + ax_cl = Axis(fig[1, 1], title="CL vs $angle_type [°]", + xlabel="$angle_type [°]", ylabel="CL") + ax_cd = Axis(fig[1, 2], title="CD vs $angle_type [°]", + xlabel="$angle_type [°]", ylabel="CD") + ax_cs = Axis(fig[2, 1], title="CS vs $angle_type [°]", + xlabel="$angle_type [°]", ylabel="CS") + ax_polar = Axis(fig[2, 2], title="CL vs CD", + xlabel="CD", ylabel="CL") + + # Number of computational results + n_solvers = length(solver_list) + + # Plot CL vs angle + for (i, (polar_data, label)) in enumerate(zip(polar_data_list, labels_with_re)) + marker = i <= n_solvers ? :star5 : :circle + markersize = i <= n_solvers ? 12 : 8 + scatterlines!(ax_cl, polar_data[1], polar_data[2]; + label=label, marker=marker, markersize=markersize) + if maximum(polar_data[2]) > 10 + ylims!(ax_cl, -0.5, 2) + end + end + axislegend(ax_cl, position=:lt) + + # Plot CD vs angle + for (i, (polar_data, label)) in enumerate(zip(polar_data_list, labels_with_re)) + marker = i <= n_solvers ? :star5 : :circle + markersize = i <= n_solvers ? 12 : 8 + scatterlines!(ax_cd, polar_data[1], polar_data[3]; + label=label, marker=marker, markersize=markersize) + if maximum(polar_data[2]) > 10 + ylims!(ax_cd, -0.5, 2) + end + end + axislegend(ax_cd, position=:lt) + + # Plot CS vs angle + for (i, (polar_data, label)) in enumerate(zip(polar_data_list, labels_with_re)) + marker = i <= n_solvers ? :star5 : :circle + markersize = i <= n_solvers ? 12 : 8 + scatterlines!(ax_cs, polar_data[1], polar_data[4]; + label=label, marker=marker, markersize=markersize) + if maximum(polar_data[2]) > 10 + ylims!(ax_cs, -0.5, 2) + end + end + axislegend(ax_cs, position=:lt) + + # Plot CL vs CD + for (i, (polar_data, label)) in enumerate(zip(polar_data_list, labels_with_re)) + marker = i <= n_solvers ? :star5 : :circle + markersize = i <= n_solvers ? 12 : 8 + scatterlines!(ax_polar, polar_data[3], polar_data[2]; + label=label, marker=marker, markersize=markersize) + if maximum(polar_data[2]) > 10 || maximum(polar_data[3]) > 10 + ylims!(ax_polar, -0.5, 2) + xlims!(ax_polar, -0.5, 2) + end + end + axislegend(ax_polar, position=:lt) + + # Save and show + if is_save && !isnothing(save_path) + save_plot(fig, save_path, main_title; data_type) + end + + if is_show + display(fig) + end + + return fig +end + +""" + plot_polar_data(body_aero::BodyAerodynamics; + alphas=collect(deg2rad.(-5:0.3:25)), + delta_tes=collect(deg2rad.(-5:0.3:25)), + is_show=true, use_tex=false) + +Plot polar data (Cl, Cd, Cm) as 3D surfaces using Makie. + +# Arguments +- `body_aero`: Wing aerodynamics struct + +# Keyword arguments +- `alphas`: Range of AoA values [rad] (default: -5° to 25° in 0.3° steps) +- `delta_tes`: Range of trailing edge angles [rad] (default: -5° to 25° in 0.3° steps) +- `is_show`: Whether to display (default: true) +- `use_tex`: Ignored for Makie (default: false) +""" +function VortexStepMethod.plot_polar_data(body_aero::BodyAerodynamics; + alphas=collect(deg2rad.(-5:0.3:25)), + delta_tes=collect(deg2rad.(-5:0.3:25)), + is_show=true, + use_tex=false) + + if body_aero.panels[1].aero_model == POLAR_MATRICES + # Create figure with 3 subplots + fig = Figure(size=(1500, 600)) + + # Get interpolation functions + interp_data = [ + (body_aero.panels[1].cl_interp, "Cl"), + (body_aero.panels[1].cd_interp, "Cd"), + (body_aero.panels[1].cm_interp, "Cm") + ] + + # Create each subplot + for (idx, (interp, label)) in enumerate(interp_data) + ax = Axis3(fig[1, idx]; + title="$label vs α and δ", + xlabel="δ [rad]", + ylabel="α [rad]", + zlabel=label, + azimuth=1.275*π) + + # Create interpolation matrix + interp_matrix = [interp(alpha, delta_te) + for alpha in alphas, delta_te in delta_tes] + + # Create wireframe + wireframe!(ax, delta_tes, alphas, interp_matrix; + color=:blue, linewidth=0.5, transparency=true) + end + + if is_show + display(fig) + end + return fig + else + throw(ArgumentError( + "Plotting polar data for $(body_aero.panels[1].aero_model) not implemented." + )) + end +end + end diff --git a/src/panel.jl b/src/panel.jl index 23886f4d..ba2e2448 100644 --- a/src/panel.jl +++ b/src/panel.jl @@ -535,4 +535,4 @@ function calculate_velocity_induced_bound_2D!( cross_square .= cross_.^2 U_2D .= (cross_ ./ sum(cross_square) ./ 2π) .* norm(r0) return nothing -end \ No newline at end of file +end diff --git a/src/plotting.jl b/src/plotting.jl deleted file mode 100644 index 3c602edb..00000000 --- a/src/plotting.jl +++ /dev/null @@ -1,920 +0,0 @@ - -""" - set_plot_style(titel_size=16; use_tex=false) - -Set the default style for plots using LaTeX. -`` -# Arguments: -- `titel_size`: size of the plot title in points (default: 16) -- `ùse_tex`: if the external `pdflatex` command shall be used -""" -function set_plot_style(titel_size=16; use_tex=false) - rcParams = plt.PyDict(plt.matplotlib."rcParams") - rcParams["text.usetex"] = use_tex - rcParams["font.family"] = "serif" - if use_tex - rcParams["font.serif"] = ["Computer Modern Roman"] - end - rcParams["axes.titlesize"] = titel_size - rcParams["axes.labelsize"] = 12 - rcParams["axes.linewidth"] = 1 - rcParams["lines.linewidth"] = 1 - rcParams["lines.markersize"] = 6 - rcParams["xtick.labelsize"] = 10 - rcParams["ytick.labelsize"] = 10 - rcParams["legend.fontsize"] = 10 - rcParams["figure.titlesize"] = 16 - if use_tex - rcParams["pgf.texsystem"] = "pdflatex" # Use pdflatex - end - rcParams["pgf.rcfonts"] = false - rcParams["figure.figsize"] = (10, 6) # Default figure size -end - - -""" - save_plot(fig, save_path, title; data_type=".pdf") - -Save a plot to a file. - -# Arguments -- `fig`: Plots figure object -- `save_path`: Path to save the plot -- `title`: Title of the plot - -# Keyword arguments -- `data_type`: File extension (default: ".pdf") -""" -function VortexStepMethod.save_plot(fig, save_path, title; data_type=".pdf") - isnothing(save_path) && throw(ArgumentError("save_path should be provided")) - - !isdir(save_path) && mkpath(save_path) - full_path = joinpath(save_path, title * data_type) - - @debug "Attempting to save figure to: $full_path" - @debug "Current working directory: $(pwd())" - - try - fig.savefig(full_path) - @debug "Figure saved as $data_type" - - if isfile(full_path) - @debug "File successfully saved to $full_path" - @debug "File size: $(filesize(full_path)) bytes" - else - @info "File does not exist after save attempt: $full_path" - end - catch e - @error "Error saving figure: $e" - @error "Error type: $(typeof(e))" - rethrow(e) - end -end - -""" - show_plot(fig; dpi=130) - -Display a plot at specified DPI. - -# Arguments -- `fig`: Plots figure object - -# Keyword arguments -- `dpi`: Dots per inch for the figure (default: 130) -""" -function VortexStepMethod.show_plot(fig; dpi=130) - plt.display(fig) -end - -""" - plot_line_segment!(ax, segment, color, label; width=3) - -Plot a line segment in 3D with arrow. - -# Arguments -- `ax`: Plot axis -- `segment`: Array of two points defining the segment -- `color`: Color of the segment -- `label`: Label for the legend - -# Keyword Arguments -- `width`: Line width (default: 3) -""" -function plot_line_segment!(ax, segment, color, label; width=3) - ax.plot( - [segment[1][1], segment[2][1]], - [segment[1][2], segment[2][2]], - [segment[1][3], segment[2][3]], - color=color, label=label, linewidth=width - ) - - dir = segment[2] - segment[1] - ax.quiver( - [segment[1][1]], [segment[1][2]], [segment[1][3]], - [dir[1]], [dir[2]], [dir[3]], - color=color - ) -end - -""" - set_axes_equal!(ax; zoom=1.8) - -Set 3D plot axes to equal scale. - -# Arguments -- ax: 3D plot axis - -# Keyword arguments -zoom: zoom factor (default: 1.8) -""" -function set_axes_equal!(ax; zoom=1.8) - x_lims = ax.get_xlim3d() ./ zoom - y_lims = ax.get_ylim3d() ./ zoom - z_lims = ax.get_zlim3d() ./ zoom - - x_range = abs(x_lims[2] - x_lims[1]) - y_range = abs(y_lims[2] - y_lims[1]) - z_range = abs(z_lims[2] - z_lims[1]) - - max_range = max(x_range, y_range, z_range) - - x_mid = mean(x_lims) - y_mid = mean(y_lims) - z_mid = mean(z_lims) - - ax.set_xlim3d((x_mid - max_range / 2, x_mid + max_range / 2)) - ax.set_ylim3d((y_mid - max_range / 2, y_mid + max_range / 2)) - ax.set_zlim3d((z_mid - max_range / 2, z_mid + max_range / 2)) -end - -""" - create_geometry_plot(body_aero::BodyAerodynamics, title, view_elevation, view_azimuth; - zoom=1.8, use_tex=false) - -Create a 3D plot of wing geometry including panels and filaments. - -# Arguments -- body_aero: struct of type BodyAerodynamics -- title: plot title -- view_elevation: initial view elevation angle [°] -- view_azimuth: initial view azimuth angle [°] - -# Keyword arguments -- zoom: zoom factor (default: 1.8) -""" -function create_geometry_plot(body_aero::BodyAerodynamics, title, view_elevation, view_azimuth; - zoom=1.8, use_tex=false) - set_plot_style(28; use_tex) - - panels = body_aero.panels - va = isa(body_aero.va, Tuple) ? body_aero.va[1] : body_aero.va - - # Extract geometric data - corner_points = [panel.corner_points for panel in panels] - control_points = [panel.control_point for panel in panels] - aero_centers = [panel.aero_center for panel in panels] - - # Create plot - fig = plt.figure(figsize=(14, 14)) - ax = fig.add_subplot(111, projection="3d") - ax.set_title(title) - - # Plot panels - legend_used = Dict{String,Bool}() - for (i, panel) in enumerate(panels) - # Plot panel edges and surfaces - corners = Matrix{Float64}(panel.corner_points) - x_corners = corners[1, :] - y_corners = corners[2, :] - z_corners = corners[3, :] - - push!(x_corners, x_corners[1]) - push!(y_corners, y_corners[1]) - push!(z_corners, z_corners[1]) - - ax.plot(x_corners, - y_corners, - z_corners, - color=:grey, - linewidth=1, - label=i == 1 ? "Panel Edges" : "") - - # Plot control points and aerodynamic centers - ax.scatter([control_points[i][1]], [control_points[i][2]], [control_points[i][3]], - color=:green, label=i == 1 ? "Control Points" : "") - ax.scatter([aero_centers[i][1]], [aero_centers[i][2]], [aero_centers[i][3]], - color=:blue, label=i == 1 ? "Aerodynamic Centers" : "") - - # Plot filaments - filaments = calculate_filaments_for_plotting(panel) - legends = ["Bound Vortex", "side1", "side2", "wake_1", "wake_2"] - - for (filament, legend) in zip(filaments, legends) - x1, x2, color = filament - @debug "Legend: $legend" - show_legend = !get(legend_used, legend, false) - plot_line_segment!(ax, [x1, x2], color, show_legend ? legend : "") - legend_used[legend] = true - end - end - - # Plot velocity vector - max_chord = maximum(panel.chord for panel in panels) - va_mag = norm(va) - va_vector_begin = -2 * max_chord * va / va_mag - va_vector_end = va_vector_begin + 1.5 * va / va_mag - plot_line_segment!(ax, [va_vector_begin, va_vector_end], :lightblue, "va") - - # Add legends for the first occurrence of each label - handles, labels = ax.get_legend_handles_labels() - # by_label = Dict(zip(labels, handles)) - # ax.legend(values(by_label), keys(by_label), bbox_to_anchor=(0, 0, 1.1, 1)) - - # Set labels and make axes equal - ax.set_xlabel("x") - ax.set_ylabel("y") - ax.set_zlabel("z") - set_axes_equal!(ax; zoom) - - # Set the initial view - ax.view_init(elev=view_elevation, azim=view_azimuth) - - # Ensure the figure is fully rendered - # fig.canvas.draw() - plt.tight_layout(rect=(0, 0, 1, 0.97)) - - return fig -end - -""" - plot_geometry(body_aero::BodyAerodynamics, title; - data_type=".pdf", save_path=nothing, - is_save=false, is_show=false, - view_elevation=15, view_azimuth=-120, use_tex=false) - -Plot wing geometry from different viewpoints and optionally save/show plots. - -# Arguments: -- `body_aero`: the [BodyAerodynamics](@ref) to plot -- title: plot title - -# Keyword arguments: -- `data_type``: string with the file type postfix (default: ".pdf") -- `save_path`: path for saving the graphic (default: `nothing`) -- `is_save`: boolean value, indicates if the graphic shall be saved (default: `false`) -- `is_show`: boolean value, indicates if the graphic shall be displayed (default: `false`) -- `view_elevation`: initial view elevation angle (default: 15) [°] -- `view_azimuth`: initial view azimuth angle (default: -120) [°] -- `use_tex`: if the external `pdflatex` command shall be used (default: false) - -""" -function VortexStepMethod.plot_geometry(body_aero::BodyAerodynamics, title; - data_type=".pdf", - save_path=nothing, - is_save=false, - is_show=false, - view_elevation=15, - view_azimuth=-120, - use_tex=false) - - if is_save - plt.ioff() - # Angled view - fig = create_geometry_plot(body_aero, "$(title)_angled_view", 15, -120; use_tex) - save_plot(fig, save_path, "$(title)_angled_view", data_type=data_type) - - # Top view - fig = create_geometry_plot(body_aero, "$(title)_top_view", 90, 0; use_tex) - save_plot(fig, save_path, "$(title)_top_view", data_type=data_type) - - # Front view - fig = create_geometry_plot(body_aero, "$(title)_front_view", 0, 0; use_tex) - save_plot(fig, save_path, "$(title)_front_view", data_type=data_type) - - # Side view - fig = create_geometry_plot(body_aero, "$(title)_side_view", 0, -90; use_tex) - save_plot(fig, save_path, "$(title)_side_view", data_type=data_type) - end - - if is_show - plt.ion() - fig = create_geometry_plot(body_aero, title, view_elevation, view_azimuth; use_tex) - plt.display(fig) - else - fig = create_geometry_plot(body_aero, title, view_elevation, view_azimuth; use_tex) - end - fig -end - -""" - plot_distribution(y_coordinates_list, results_list, label_list; - title="spanwise_distribution", data_type=".pdf", - save_path=nothing, is_save=false, is_show=true, use_tex=false) - -Plot spanwise distributions of aerodynamic properties. - -# Arguments -- `y_coordinates_list`: List of spanwise coordinates -- `results_list`: List of result dictionaries -- `label_list`: List of labels for different results - -# Keyword arguments -- `title`: Plot title (default: "spanwise_distribution") -- `data_type`: File extension for saving (default: ".pdf") -- `save_path`: Path to save plots (default: nothing) -- `is_save`: Whether to save plots (default: false) -- `is_show`: Whether to display plots (default: true) -- `use_tex`: if the external `pdflatex` command shall be used -""" -function VortexStepMethod.plot_distribution(y_coordinates_list, results_list, label_list; - title="spanwise_distribution", - data_type=".pdf", - save_path=nothing, - is_save=false, - is_show=true, - use_tex=false) - - length(results_list) == length(label_list) || throw(ArgumentError( - "Number of results ($(length(results_list))) must match number of labels ($(length(label_list)))" - )) - - # Set the plot style - set_plot_style(; use_tex) - - # Initializing plot - fig, axs = plt.subplots(3, 3, figsize=(16, 10)) - fig.suptitle(title, fontsize=16) - - # CL plot - for (y_coordinates_i, result_i, label_i) in zip(y_coordinates_list, results_list, label_list) - value = "$(round(result_i["cl"], digits=2))" - if label_i == "LLT" - label = label_i * L" $~C_\mathrm{L}$: " * value - else - label = label_i * L" $C_\mathrm{L}$: " * value - end - axs[1, 1].plot( - y_coordinates_i, - result_i["cl_distribution"], - label=label - ) - end - axs[1, 1].set_title(L"$C_\mathrm{L}$ Distribution", size=16) - axs[1, 1].set_xlabel(L"Spanwise Position $y/b$") - axs[1, 1].set_ylabel(L"Lift Coefficient $C_\mathrm{L}$") - axs[1, 1].legend() - - # CD plot - for (y_coordinates_i, result_i, label_i) in zip(y_coordinates_list, results_list, label_list) - value = "$(round(result_i["cl"], digits=2))" - if label_i == "LLT" - label = label_i * L" $~C_\mathrm{D}$: " * value - else - label = label_i * L" $C_\mathrm{D}$: " * value - end - axs[1, 2].plot( - y_coordinates_i, - result_i["cd_distribution"], - label=label - ) - end - axs[1, 2].set_title(L"$C_\mathrm{D}$ Distribution", size=16) - axs[1, 2].set_xlabel(L"Spanwise Position $y/b$") - axs[1, 2].set_ylabel(L"Drag Coefficient $C_\mathrm{D}$") - axs[1, 2].legend() - - # Gamma Distribution - for (y_coordinates_i, result_i, label_i) in zip(y_coordinates_list, results_list, label_list) - axs[1, 3].plot( - y_coordinates_i, - result_i["gamma_distribution"], - label=label_i - ) - end - axs[1, 3].set_title(L"\Gamma~Distribution", size=16) - axs[1, 3].set_xlabel(L"Spanwise Position $y/b$") - axs[1, 3].set_ylabel(L"Circulation~\Gamma") - axs[1, 3].legend() - - # Geometric Alpha - for (y_coordinates_i, result_i, label_i) in zip(y_coordinates_list, results_list, label_list) - axs[2, 1].plot( - y_coordinates_i, - result_i["alpha_geometric"], - label=label_i - ) - end - axs[2, 1].set_title(L"$\alpha$ Geometric", size=16) - axs[2, 1].set_xlabel(L"Spanwise Position $y/b$") - axs[2, 1].set_ylabel(L"Angle of Attack $\alpha$ (deg)") - axs[2, 1].legend() - - # Calculated/ Corrected Alpha - for (y_coordinates_i, result_i, label_i) in zip(y_coordinates_list, results_list, label_list) - axs[2, 2].plot( - y_coordinates_i, - result_i["alpha_at_ac"], - label=label_i - ) - end - axs[2, 2].set_title(L"$\alpha$ result (corrected to aerodynamic center)", size=16) - axs[2, 2].set_xlabel(L"Spanwise Position $y/b$") - axs[2, 2].set_ylabel(L"Angle of Attack $\alpha$ (deg)") - axs[2, 2].legend() - - # Uncorrected Alpha plot - for (y_coordinates_i, result_i, label_i) in zip(y_coordinates_list, results_list, label_list) - axs[2, 3].plot( - y_coordinates_i, - result_i["alpha_uncorrected"], - label=label_i - ) - end - axs[2, 3].set_title(L"$\alpha$ Uncorrected (if VSM, at the control point)", size=16) - axs[2, 3].set_xlabel(L"Spanwise Position $y/b$") - axs[2, 3].set_ylabel(L"Angle of Attack $\alpha$ (deg)") - axs[2, 3].legend() - - # Force Components - for (idx, component) in enumerate(["x", "y", "z"]) - axs[3, idx].set_title("Force in $component direction", size=16) - axs[3, idx].set_xlabel(L"Spanwise Position $y/b$") - axs[3, idx].set_ylabel(raw"$F_\mathrm" * "{$component}" * raw"$") - for (y_coords, results, label) in zip(y_coordinates_list, results_list, label_list) - # Extract force components for the current direction (idx) - forces = results["F_distribution"][idx, :] - # Verify dimensions match - if length(y_coords) != length(forces) - @warn "Dimension mismatch in force plotting" length(y_coords) length(forces) component - continue # Skip this component instead of throwing error - end - space = "" - if label == "LLT" - space = "~" - end - axs[3, idx].plot( - y_coords, - forces, - label="$label" * space * raw"$~\Sigma~F_\mathrm" * "{$component}:~" * - raw"$" * "$(round(results["F$component"], digits=2)) N" - ) - axs[3, idx].legend() - end - end - - fig.tight_layout() - - # Save and show plot - if is_save - save_plot(fig, save_path, title, data_type=data_type) - end - - if is_show - show_plot(fig) - end - - return fig -end - -""" - generate_polar_data(solver, body_aero::BodyAerodynamics, angle_range; - angle_type="angle_of_attack", angle_of_attack=0.0, - side_slip=0.0, v_a=10.0, use_latex=false) - -Generate polar data for aerodynamic analysis over a range of angles. - -# Arguments -- `solver`: Aerodynamic solver object -- `body_aero`: Wing aerodynamics struct -- `angle_range`: Range of angles to analyze - -# Keyword arguments -- `angle_type`: Type of angle variation ("angle_of_attack" or "side_slip") -- `angle_of_attack`: Initial angle of attack [rad] -- `side_slip`: Initial side slip angle in [rad] -- `v_a`: norm of apparent wind speed [m/s] - -# Returns -- Tuple of polar data array and Reynolds number -""" -function generate_polar_data( - solver, - body_aero::BodyAerodynamics, - angle_range; - angle_type="angle_of_attack", - angle_of_attack=0.0, - side_slip=0.0, - v_a=10.0, - use_latex=false -) - n_panels = length(body_aero.panels) - n_angles = length(angle_range) - - # Initialize arrays - cl = zeros(n_angles) - cd = zeros(n_angles) - cs = zeros(n_angles) - gamma_distribution = zeros(n_angles, n_panels) - cl_distribution = zeros(n_angles, n_panels) - cd_distribution = zeros(n_angles, n_panels) - cs_distribution = zeros(n_angles, n_panels) - reynolds_number = zeros(n_angles) - - # Previous gamma for initialization - gamma = nothing - - for (i, angle_i) in enumerate(angle_range) - # Set angle based on type - if angle_type == "angle_of_attack" - α = deg2rad(angle_i) - β = side_slip - elseif angle_type == raw"side_slip" - α = angle_of_attack - β = deg2rad(angle_i) - else - throw(ArgumentError("angle_type must be 'angle_of_attack' or 'side_slip'")) - end - - # Update inflow conditions - set_va!( - body_aero, - [ - cos(α) * cos(β), - sin(β), - sin(α) - ] * v_a - ) - - # Solve and store results - results = solve(solver, body_aero, gamma_distribution[i, :]) - - cl[i] = results["cl"] - cd[i] = results["cd"] - cs[i] = results["cs"] - gamma_distribution[i, :] = results["gamma_distribution"] - cl_distribution[i, :] = results["cl_distribution"] - cd_distribution[i, :] = results["cd_distribution"] - cs_distribution[i, :] = results["cs_distribution"] - reynolds_number[i] = results["Rey"] - - # Store gamma for next iteration - gamma = gamma_distribution[i, :] - end - - polar_data = [ - angle_range, - cl, - cd, - cs, - gamma_distribution, - cl_distribution, - cd_distribution, - cs_distribution, - reynolds_number - ] - - return polar_data, reynolds_number[1] -end - -""" - plot_polars(solver_list, body_aero_list, label_list; - literature_path_list=String[], - angle_range=range(0, 20, 2), angle_type="angle_of_attack", - angle_of_attack=0.0, side_slip=0.0, v_a=10.0, - title="polar", data_type=".pdf", save_path=nothing, - is_save=true, is_show=true, use_tex=false) - -Plot polar data comparing different solvers and configurations. - -# Arguments -- `solver_list`: List of aerodynamic solvers -- `body_aero_list`: List of wing aerodynamics objects -- `label_list`: List of labels for each configuration - -# Keyword arguments -- `literature_path_list`: Optional paths to literature data files -- `angle_range`: Range of angles to analyze [°] -- `angle_type`: "`angle_of_attack`" or "`side_slip`"; (default: `angle_of_attack`) -- `angle_of_attack:` AoA to be used for plotting the polars (default: 0.0) [rad] -- `side_slip`: side slip angle (default: 0.0) [rad] -- v_a: norm of apparent wind speed (default: 10.0) [m/s] -- title: plot title -- `data_type`: File extension for saving (default: ".pdf") -- `save_path`: Path to save plots (default: nothing) -- `is_save`: Whether to save plots (default: true) -- `is_show`: Whether to display plots (default: true) -- `use_tex`: if the external `pdflatex` command shall be used (default: false) -""" -function VortexStepMethod.plot_polars( - solver_list, - body_aero_list, - label_list; - literature_path_list=String[], - angle_range=range(0, 20, 2), - angle_type="angle_of_attack", - angle_of_attack=0.0, - side_slip=0.0, - v_a=10.0, - title="polar", - data_type=".pdf", - save_path=nothing, - is_save=true, - is_show=true, - use_tex=false -) - # Validate inputs - total_cases = length(body_aero_list) + length(literature_path_list) - if total_cases != length(label_list) || length(solver_list) != length(body_aero_list) - throw(ArgumentError("Mismatch in number of solvers ($(length(solver_list))), " * - "cases ($total_cases), and labels ($(length(label_list)))")) - end - main_title = replace(title, " " => "_") - set_plot_style(; use_tex) - - # Generate polar data - polar_data_list = [] - for (i, (solver, body_aero)) in enumerate(zip(solver_list, body_aero_list)) - polar_data, rey = generate_polar_data( - solver, body_aero, angle_range; - angle_type, - angle_of_attack, - side_slip, - v_a - ) - push!(polar_data_list, polar_data) - # Update label with Reynolds number - label_list[i] = "$(label_list[i]) Re = $(round(Int64, rey*1e-5))e5" - end - # Load literature data if provided - if !isempty(literature_path_list) - for path in literature_path_list - data = readdlm(path, ',') - header = lowercase.(string.(data[1, :])) - # Find column indices for alpha, CL, CD, CS (case-insensitive, allow common variants) - alpha_idx = findfirst(x -> occursin("alpha", x), header) - cl_idx = findfirst(x -> occursin("cl", x), header) - cd_idx = findfirst(x -> occursin("cd", x), header) - cs_idx = findfirst(x -> occursin("cs", x), header) - # Fallback: if CS not found, fill with zeros - cs_col = cs_idx === nothing ? zeros(size(data, 1)-1) : data[2:end, cs_idx] - # Push as [alpha, CL, CD, CS] - push!(polar_data_list, [ - data[2:end, alpha_idx], - data[2:end, cl_idx], - data[2:end, cd_idx], - cs_col - ]) - end - end - - # Initializing plot - fig, axs = plt.subplots(2, 2, figsize=(14, 14)) - - # Number of computational results (excluding literature) - n_solvers = length(solver_list) - for (i, (polar_data, label)) in enumerate(zip(polar_data_list, label_list)) - if i < n_solvers - linestyle = "-" - marker = "*" - markersize = 7 - else - linestyle = "-" - marker = "." - markersize = 5 - end - if contains(label, "LLT") - label = replace(label, "e5" => raw"\cdot10^5") - label = replace(label, " " => raw"~") - label = replace(label, "LLT" => raw"\mathrm{LLT}{~\,}") - label = raw"$" * label * raw"$" - else - label = replace(label, "e5" => raw"\cdot10^5") - label = replace(label, " " => "~") - label = replace(label, "VSM" => raw"\mathrm{VSM}") - label = raw"$" * label * raw"$" - end - axs[1, 1].plot( - polar_data[1], - polar_data[2], - label=label, - linestyle=linestyle, - marker=marker, - markersize=markersize, - ) - # Limit y-range if CL > 10 - if maximum(polar_data[2]) > 10 - axs[1, 1].set_ylim([-0.5, 2]) - end - title = raw"$C_\mathrm{L}" * raw"$" * " vs $angle_type [°]" - axs[1, 1].set_title(title) - axs[1, 1].set_xlabel("$angle_type [°]") - axs[1, 1].set_ylabel(L"$C_\mathrm{L}$") - axs[1, 1].legend() - end - - for (i, (polar_data, label)) in enumerate(zip(polar_data_list, label_list)) - if i < n_solvers - linestyle = "-" - marker = "*" - markersize = 7 - else - linestyle = "-" - marker = "." - markersize = 5 - end - if contains(label, "LLT") - label = replace(label, "e5" => raw"\cdot10^5") - label = replace(label, " " => raw"~") - label = replace(label, "LLT" => raw"\mathrm{LLT}{~\,}") - label = raw"$" * label * raw"$" - else - label = replace(label, "e5" => raw"\cdot10^5") - label = replace(label, " " => "~") - label = replace(label, "VSM" => raw"\mathrm{VSM}") - label = raw"$" * label * raw"$" - end - axs[1, 2].plot( - polar_data[1], - polar_data[3], - label=label, - linestyle=linestyle, - marker=marker, - markersize=markersize, - ) - # Limit y-range if CL > 10 - if maximum(polar_data[2]) > 10 - axs[1, 2].set_ylim([-0.5, 2]) - end - title = raw"$C_\mathrm{D}" * raw"$" * " vs $angle_type [°]" - axs[1, 2].set_title(title) - axs[1, 2].set_xlabel("$angle_type [°]") - axs[1, 2].set_ylabel(L"$C_\mathrm{D}$") - axs[1, 2].legend() - end - - - for (i, (polar_data, label)) in enumerate(zip(polar_data_list, label_list)) - if i < n_solvers - linestyle = "-" - marker = "*" - markersize = 7 - else - linestyle = "-" - marker = "." - markersize = 5 - end - if contains(label, "LLT") - label = replace(label, "e5" => raw"\cdot10^5") - label = replace(label, " " => raw"~") - label = replace(label, "LLT" => raw"\mathrm{LLT}{~\,}") - label = raw"$" * label * raw"$" - else - label = replace(label, "e5" => raw"\cdot10^5") - label = replace(label, " " => "~") - label = replace(label, "VSM" => raw"\mathrm{VSM}") - label = raw"$" * label * raw"$" - end - axs[2, 1].plot( - polar_data[1], - polar_data[4], - label=label, - linestyle=linestyle, - marker=marker, - markersize=markersize, - ) - # Limit y-range if CL > 10 - if maximum(polar_data[2]) > 10 - axs[2, 1].set_ylim([-0.5, 2]) - end - title = raw"$C_\mathrm{S}" * raw"$" * " vs $angle_type [°]" - axs[2, 1].set_title(title) - axs[2, 1].set_xlabel("$angle_type [°]") - axs[2, 1].set_ylabel(L"$C_\mathrm{S}$") - axs[2, 1].legend() - end - - for (i, (polar_data, label)) in enumerate(zip(polar_data_list, label_list)) - if i < n_solvers - linestyle = "-" - marker = "*" - markersize = 7 - else - linestyle = "-" - marker = "." - markersize = 5 - end - if contains(label, "LLT") - label = replace(label, "e5" => raw"\cdot10^5") - label = replace(label, " " => raw"~") - label = replace(label, "LLT" => raw"\mathrm{LLT}{~\,}") - label = raw"$" * label * raw"$" - else - label = replace(label, "e5" => raw"\cdot10^5") - label = replace(label, " " => "~") - label = replace(label, "VSM" => raw"\mathrm{VSM}") - label = raw"$" * label * raw"$" - end - axs[2, 2].plot( - polar_data[3], - polar_data[2], - label=label, - linestyle=linestyle, - marker=marker, - markersize=markersize, - ) - # Limit y-range if CL > 10 - if maximum(polar_data[2]) > 10 || maximum(polar_data[3]) > 10 - axs[2, 2].set_ylim([-0.5, 2]) - axs[2, 2].set_xlim([-0.5, 2]) - end - title = raw"$C_\mathrm{L}" * raw"$" * " vs " * raw"$C_\mathrm{D}" * raw"$" - axs[2, 2].set_title(title) - axs[2, 2].set_xlabel(L"$C_\mathrm{D}$") - axs[2, 2].set_ylabel(L"$C_\mathrm{L}$") - axs[2, 2].legend() - end - - fig.tight_layout(h_pad=3.5, rect=(0.01, 0.01, 0.99, 0.99)) - - # Save and show plot - if is_save && !isnothing(save_path) - save_plot(fig, save_path, main_title; data_type) - end - - if is_show - show_plot(fig) - end - - return fig -end - -""" - plot_polar_data(body_aero::BodyAerodynamics; alphas=collect(deg2rad.(-5:0.3:25)), delta_tes=collect(deg2rad.(-5:0.3:25))) - -Plot polar data (Cl, Cd, Cm) as 3D surfaces against alpha and delta_te angles. delta_te is the trailing edge deflection angle -relative to the 2d airfoil or panel chord line. - -# Arguments -- `body_aero`: Wing aerodynamics struct - -# Keyword arguments -- `alphas`: Range of angle of attack values in radians (default: -5° to 25° in 0.3° steps) -- `delta_tes`: Range of trailing edge angles in radians (default: -5° to 25° in 0.3° steps) -- `is_show`: Whether to display plots (default: true) -- `use_tex`: if the external `pdflatex` command shall be used -""" -function VortexStepMethod.plot_polar_data(body_aero::BodyAerodynamics; - alphas=collect(deg2rad.(-5:0.3:25)), - delta_tes = collect(deg2rad.(-5:0.3:25)), - is_show = true, - use_tex = false - ) - if body_aero.panels[1].aero_model == POLAR_MATRICES - set_plot_style() - - # Create figure with subplots - fig = plt.figure(figsize=(15, 6)) - - # Get interpolation functions and labels - interp_data = [ - (body_aero.panels[1].cl_interp, L"$C_l$"), - (body_aero.panels[1].cd_interp, L"$C_d$"), - (body_aero.panels[1].cm_interp, L"$C_m$") - ] - - # Create each subplot - for (idx, (interp, label)) in enumerate(interp_data) - ax = fig.add_subplot(1, 3, idx, projection="3d") - - # Create interpolation matrix - interp_matrix = zeros(length(alphas), length(delta_tes)) - interp_matrix .= [interp(alpha, delta_te) for alpha in alphas, delta_te in delta_tes] - X = collect(delta_tes) .+ zeros(length(alphas))' - Y = collect(alphas)' .+ zeros(length(delta_tes)) - - # Plot surface - ax.plot_wireframe(X, Y, interp_matrix, - edgecolor="blue", - lw=0.5, - rstride=5, - cstride=5, - alpha=0.6) - - # Set labels and title - ax.set_xlabel(L"$\delta$ [rad]") - ax.set_ylabel(L"$\alpha$ [rad]") - ax.set_zlabel(label) - ax.set_title(label * L" vs $\alpha$ and $\delta$") - ax.grid(true) - end - - # Adjust layout and display - plt.tight_layout(rect=(0.01, 0.01, 0.99, 0.99)) - if is_show - show_plot(fig) - end - return fig - else - throw(ArgumentError("Plotting polar data for $(body_aero.panels[1].aero_model) is not implemented.")) - end -end From 084e7bb9368009ca7ef0924dd37b091bf41b14a5 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sun, 16 Nov 2025 22:09:09 +0100 Subject: [PATCH 23/86] Don't use corrected alpha --- src/VortexStepMethod.jl | 2 +- src/body_aerodynamics.jl | 23 ++++++++++++----------- src/settings.jl | 8 +++++++- src/solver.jl | 5 ++++- 4 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/VortexStepMethod.jl b/src/VortexStepMethod.jl index f3cb531a..8c1a407a 100644 --- a/src/VortexStepMethod.jl +++ b/src/VortexStepMethod.jl @@ -294,4 +294,4 @@ include("solver.jl") include("precompile.jl") -end # module \ No newline at end of file +end # module diff --git a/src/body_aerodynamics.jl b/src/body_aerodynamics.jl index b96ff57d..97803526 100644 --- a/src/body_aerodynamics.jl +++ b/src/body_aerodynamics.jl @@ -449,7 +449,8 @@ function calculate_results( va_norm_array, va_unit_array, panels::Vector{Panel}, - is_only_f_and_gamma_output::Bool, + is_only_f_and_gamma_output::Bool; + correct_aoa::Bool=false, ) # Initialize arrays @@ -473,7 +474,7 @@ function calculate_results( moment = reshape((cm_array .* 0.5 .* density .* v_a_array.^2 .* chord_array), :, 1) # Calculate alpha corrections based on model type - if aerodynamic_model_type == VSM + if correct_aoa update_effective_angle_of_attack!( alpha_corrected, body_aero, @@ -485,7 +486,7 @@ function calculate_results( va_norm_array, va_unit_array ) - elseif aerodynamic_model_type == LLT + else alpha_corrected .= alpha_array end @@ -661,8 +662,7 @@ Set velocity array and update wake filaments. - `va::VelVector`: Velocity vector of the apparent wind speed [m/s] - `omega::VelVector`: Turn rate vector around x y and z axis [rad/s] """ -function set_va!(body_aero::BodyAerodynamics, va::VelVector, omega=zeros(MVec3)) - +function set_va!(body_aero::BodyAerodynamics, va::AbstractVector, omega=zeros(MVec3)) # Calculate va_distribution based on input type va_distribution = if all(omega .== 0.0) repeat(reshape(va, 1, 3), length(body_aero.panels)) @@ -693,16 +693,17 @@ function set_va!(body_aero::BodyAerodynamics, va::VelVector, omega=zeros(MVec3)) return nothing end -function set_va!(body_aero::BodyAerodynamics, va_distribution::Vector{VelVector}, omega=zeros(MVec3)) - length(va) != length(body_aero.panels) && throw(ArgumentError("Length of va distribution should be equal to number of panels.")) - +function set_va!(body_aero::BodyAerodynamics, va_distribution::AbstractMatrix, omega=zeros(MVec3)) + size(va_distribution, 1) != length(body_aero.panels) && + throw(ArgumentError("Number of rows in va distribution should be equal to number of panels.")) + for (i, panel) in enumerate(body_aero.panels) - panel.va = va_distribution[i] + panel.va .= va_distribution[i, :] end - + # Update wake elements frozen_wake!(body_aero, va_distribution) - body_aero._va = va + body_aero._va .= [mean(va_distribution[:,i]) for i in 1:3] return nothing end diff --git a/src/settings.jl b/src/settings.jl index 5916da52..ea19b4d1 100644 --- a/src/settings.jl +++ b/src/settings.jl @@ -35,6 +35,7 @@ end core_radius_fraction::Float64 = 1e-20 mu::Float64 = 1.81e-5 # dynamic viscosity [N·s/m²] calc_only_f_and_gamma::Bool=false # whether to only output f and gamma + correct_aoa::Bool=false # perform aoa correction end @Base.kwdef mutable struct VSMSettings @@ -107,7 +108,12 @@ function VSMSettings(filename; data_prefix=true) # Handle enum conversions manually vsm_settings.solver_settings.aerodynamic_model_type = eval(Symbol(solver_data["aerodynamic_model_type"])) vsm_settings.solver_settings.type_initial_gamma_distribution = eval(Symbol(solver_data["type_initial_gamma_distribution"])) - + + # Set correct_aoa default based on model type if not explicitly provided + if !haskey(solver_data, "correct_aoa") + vsm_settings.solver_settings.correct_aoa = (vsm_settings.solver_settings.aerodynamic_model_type == VSM) + end + # Override with calculated totals vsm_settings.solver_settings.n_panels = n_panels vsm_settings.solver_settings.n_groups = n_groups diff --git a/src/solver.jl b/src/solver.jl index cb7cc6be..e273929c 100644 --- a/src/solver.jl +++ b/src/solver.jl @@ -123,6 +123,7 @@ sol::VSMSolution = VSMSolution(): The result of calling [solve!](@ref) core_radius_fraction::Float64 = 1e-20 mu::Float64 = 1.81e-5 is_only_f_and_gamma_output::Bool = false + correct_aoa::Bool = false # Intermediate results lr::LoopResult{P} = LoopResult{P}() @@ -149,6 +150,7 @@ function Solver(body_aero, settings::VSMSettings) rtol=settings.solver_settings.rtol, relaxation_factor=settings.solver_settings.relaxation_factor, core_radius_fraction=settings.solver_settings.core_radius_fraction, + correct_aoa=settings.solver_settings.correct_aoa, ) end @@ -485,7 +487,8 @@ function solve(solver::Solver, body_aero::BodyAerodynamics, gamma_distribution=n solver.br.va_norm_array, solver.br.va_unit_array, body_aero.panels, - solver.is_only_f_and_gamma_output + solver.is_only_f_and_gamma_output; + correct_aoa=solver.correct_aoa ) return results end From 112fcede60e9ae27535636bc3e5405ef850f7c92 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sun, 16 Nov 2025 22:09:24 +0100 Subject: [PATCH 24/86] Updated settings --- test/settings/test_settings.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/settings/test_settings.jl b/test/settings/test_settings.jl index e3200766..68566cae 100644 --- a/test/settings/test_settings.jl +++ b/test/settings/test_settings.jl @@ -11,6 +11,6 @@ using Test @test vss.wings isa Vector{WingSettings} @test length(vss.wings) == 2 io = IOBuffer(repr(vss)) - @test countlines(io) == 46 # Updated to match new output format + @test countlines(io) == 47 # Updated to match new output format end nothing From 2031982128e101f43c7dac20aa699800da3ee0aa Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sun, 16 Nov 2025 22:09:40 +0100 Subject: [PATCH 25/86] Use plot and plot! with obs --- ext/VortexStepMethodMakieExt.jl | 204 +++++++++++++++++++++++++++++--- 1 file changed, 187 insertions(+), 17 deletions(-) diff --git a/ext/VortexStepMethodMakieExt.jl b/ext/VortexStepMethodMakieExt.jl index 69819d2a..203e7e1b 100644 --- a/ext/VortexStepMethodMakieExt.jl +++ b/ext/VortexStepMethodMakieExt.jl @@ -4,55 +4,193 @@ import VortexStepMethod: calculate_filaments_for_plotting export plot_geometry, plot_distribution, plot_polars, save_plot, show_plot, plot_polar_data +# Global storage for panel mesh observables (for dynamic plotting) +const PANEL_MESH_OBSERVABLES = Ref{Union{Nothing, Dict}}(nothing) + """ - plot!(ax, panel::VortexStepMethod.Panel; kwargs...) + plot!(ax, panel::VortexStepMethod.Panel; use_observables=false, kwargs...) Plot a single `Panel` as a `mesh`. The corner points are ordered as: LE1, TE1, TE2, LE2. This creates two triangles: (LE1, TE1, TE2) and (LE1, TE2, LE2). + +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, kwargs...) +function Makie.plot!(ax, panel::VortexStepMethod.Panel; color=(:red, 0.2), R_b_w=nothing, T_b_w=nothing, + use_observables=false, kwargs...) plots = [] points = [Point3f(panel.corner_points[:, i]) for i in 1:4] if !isnothing(R_b_w) && !isnothing(T_b_w) points = [Point3f(R_b_w * p + T_b_w) for p in points] end - faces = [Makie.GLTriangleFace(1, 2, 3), Makie.GLTriangleFace(1, 3, 4)] - p = mesh!(ax, points, faces; color, transparency=true, kwargs...) - push!(plots, p) - border_points = [points..., points[1]] - p = lines!(ax, border_points; color=:black, transparency=true, kwargs...) - push!(plots, p) + + if use_observables + # Create observables for dynamic updates + vertices_obs = Observable(points) + faces_obs = Observable([Makie.GLTriangleFace(1, 2, 3), Makie.GLTriangleFace(1, 3, 4)]) + border_obs = Observable([points..., points[1]]) + + p = mesh!(ax, vertices_obs, faces_obs; color, transparency=true, kwargs...) + push!(plots, p) + p = lines!(ax, border_obs; color=:black, transparency=true, kwargs...) + push!(plots, p) + + # Note: Observables are stored at the body level, not individual panel level + # Individual panels need their parent body for proper tracking + else + # Static plotting (original behavior) + faces = [Makie.GLTriangleFace(1, 2, 3), Makie.GLTriangleFace(1, 3, 4)] + p = mesh!(ax, points, faces; color, transparency=true, kwargs...) + push!(plots, p) + border_points = [points..., points[1]] + p = lines!(ax, border_points; color=:black, transparency=true, kwargs...) + push!(plots, p) + end + return plots end """ - plot!(ax, body::VortexStepMethod.BodyAerodynamics; kwargs...) + plot!(ax, body::VortexStepMethod.BodyAerodynamics; use_observables=false, kwargs...) Plot a `BodyAerodynamics` object by plotting each of its panels. + +If `use_observables=true`, creates observables for dynamic updates keyed by (body_id, panel_index). +Otherwise, creates static plots (original behavior). """ -function Makie.plot!(ax, body::VortexStepMethod.BodyAerodynamics; color=(:red, 0.2), R_b_w=nothing, T_b_w=nothing, kwargs...) +function Makie.plot!(ax, body::VortexStepMethod.BodyAerodynamics; color=(:red, 0.2), R_b_w=nothing, T_b_w=nothing, + use_observables=false, kwargs...) plots = [] - for panel in body.panels - p = Makie.plot!(ax, panel; color, R_b_w, T_b_w, kwargs...) - push!(plots, p) + + if use_observables + # Initialize global storage if needed + if isnothing(PANEL_MESH_OBSERVABLES[]) + PANEL_MESH_OBSERVABLES[] = Dict() + end + + body_id = objectid(body) + + # Create observables for each panel + for (panel_idx, panel) in enumerate(body.panels) + # Compute initial points + points = [Point3f(panel.corner_points[:, i]) for i in 1:4] + if !isnothing(R_b_w) && !isnothing(T_b_w) + points = [Point3f(R_b_w * p + T_b_w) for p in points] + end + + # Create observables + vertices_obs = Observable(points) + faces_obs = Observable([Makie.GLTriangleFace(1, 2, 3), Makie.GLTriangleFace(1, 3, 4)]) + border_obs = Observable([points..., points[1]]) + + # Plot using observables + p = mesh!(ax, vertices_obs, faces_obs; color, transparency=true, kwargs...) + push!(plots, p) + p = lines!(ax, border_obs; color=:black, transparency=true, kwargs...) + push!(plots, p) + + # Store observables with stable key + PANEL_MESH_OBSERVABLES[][(body_id, panel_idx)] = ( + vertices = vertices_obs, + border = border_obs, + faces = faces_obs + ) + end + 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, kwargs...) + push!(plots, p) + end end + return plots end -function Makie.plot(panel::VortexStepMethod.Panel; size = (1200, 800), kwargs...) + +""" + plot!(body::VortexStepMethod.BodyAerodynamics; R_b_w=nothing, T_b_w=nothing) + +Update existing body aerodynamics plot observables with current geometry. +This updates all panels in the body using their current corner_points. + +Requires that `plot(body; use_observables=true)` or `plot!(ax, body; use_observables=true)` +was called first to create the observables. +""" +function Makie.plot!(body::VortexStepMethod.BodyAerodynamics; R_b_w=nothing, T_b_w=nothing, kwargs...) + # Check if observables exist + if isnothing(PANEL_MESH_OBSERVABLES[]) + error("No panel observables found. Call plot(body; use_observables=true) first.") + end + + body_id = objectid(body) + + # Update each panel using stable (body_id, panel_idx) key + for (panel_idx, panel) in enumerate(body.panels) + key = (body_id, panel_idx) + if !haskey(PANEL_MESH_OBSERVABLES[], key) + error("No observables found for body $body_id panel $panel_idx. " * + "Call plot(body; use_observables=true) first.") + end + + # Get observables for this panel + obs = PANEL_MESH_OBSERVABLES[][key] + + # Recompute vertices from current panel.corner_points + points = [Point3f(panel.corner_points[:, i]) for i in 1:4] + if !isnothing(R_b_w) && !isnothing(T_b_w) + points = [Point3f(R_b_w * p + T_b_w) for p in points] + end + + # Update observables + obs.vertices[] = points + obs.border[] = [points..., points[1]] + end + + return nothing +end + +function Makie.plot(panel::VortexStepMethod.Panel; size = (1200, 800), + R_b_w=nothing, T_b_w=nothing, color=(:red, 0.2), kwargs...) fig = Figure(; size) ax = Axis3(fig[1, 1]; aspect = :data, xlabel = "X", ylabel = "Y", zlabel = "Z", azimuth = 9/8*π, zoommode = :cursor, viewmode = :fit, ) - plot!(ax, panel; kwargs...) + # Create observables for panel geometry + points = [Point3f(panel.corner_points[:, i]) for i in 1:4] + if !isnothing(R_b_w) && !isnothing(T_b_w) + points = [Point3f(R_b_w * p + T_b_w) for p in points] + end + + vertices_obs = Observable(points) + faces_obs = Observable([Makie.GLTriangleFace(1, 2, 3), Makie.GLTriangleFace(1, 3, 4)]) + + # Plot mesh using observables + mesh!(ax, vertices_obs, faces_obs; color, transparency=true, kwargs...) + + # Plot border + border_obs = Observable([points..., points[1]]) + lines!(ax, border_obs; color=:black, transparency=true, kwargs...) + + # Store observables globally for updates + panel_id = objectid(panel) + if isnothing(PANEL_MESH_OBSERVABLES[]) + PANEL_MESH_OBSERVABLES[] = Dict() + end + PANEL_MESH_OBSERVABLES[][panel_id] = ( + vertices = vertices_obs, + border = border_obs, + faces = faces_obs + ) + return fig end function Makie.plot(body_aero::VortexStepMethod.BodyAerodynamics; size = (1200, 800), - limitmargin = 0.1, kwargs...) + limitmargin = 0.1, R_b_w=nothing, T_b_w=nothing, color=(:red, 0.2), + kwargs...) fig = Figure(; size) ax = Axis3(fig[1, 1]; aspect = :data, xlabel = "X", ylabel = "Y", zlabel = "Z", @@ -61,7 +199,39 @@ function Makie.plot(body_aero::VortexStepMethod.BodyAerodynamics; size = (1200, yautolimitmargin=(limitmargin, limitmargin), zautolimitmargin=(limitmargin, limitmargin), ) - plot!(ax, body_aero; kwargs...) + + # Initialize global storage if needed + if isnothing(PANEL_MESH_OBSERVABLES[]) + PANEL_MESH_OBSERVABLES[] = Dict() + end + + body_id = objectid(body_aero) + + # Create observables for each panel using stable (body_id, panel_idx) key + for (panel_idx, panel) in enumerate(body_aero.panels) + # Compute initial points + points = [Point3f(panel.corner_points[:, i]) for i in 1:4] + if !isnothing(R_b_w) && !isnothing(T_b_w) + points = [Point3f(R_b_w * p + T_b_w) for p in points] + end + + # Create observables + vertices_obs = Observable(points) + faces_obs = Observable([Makie.GLTriangleFace(1, 2, 3), Makie.GLTriangleFace(1, 3, 4)]) + border_obs = Observable([points..., points[1]]) + + # Plot using observables + mesh!(ax, vertices_obs, faces_obs; color, transparency=true, kwargs...) + lines!(ax, border_obs; color=:black, transparency=true, kwargs...) + + # Store observables with stable key + PANEL_MESH_OBSERVABLES[][(body_id, panel_idx)] = ( + vertices = vertices_obs, + border = border_obs, + faces = faces_obs + ) + end + return fig end From e23eb99d9721fa3b54c6c57503bca299dc339ecf Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Fri, 21 Nov 2025 16:43:09 +0100 Subject: [PATCH 26/86] Use unrefined sections --- examples/stall_model.jl | 7 +- ext/VortexStepMethodMakieExt.jl | 6 +- src/VortexStepMethod.jl | 9 +- src/body_aerodynamics.jl | 19 +- src/obj_geometry.jl | 53 +++-- src/solver.jl | 201 +++++++----------- src/wing_geometry.jl | 53 ++--- src/yaml_geometry.jl | 28 ++- test/body_aerodynamics/complete_settings.yaml | 1 - test/ram_geometry/test_kite_geometry.jl | 2 +- test/solver/solver_settings.yaml | 1 - test/solver/test_group_coefficients.jl | 200 ++++++++--------- test/wing_geometry/test_wing_geometry.jl | 17 +- test/yaml_geometry/test_wing_constructor.jl | 30 +-- .../test_yaml_wing_deformation.jl | 10 +- 15 files changed, 303 insertions(+), 334 deletions(-) diff --git a/examples/stall_model.jl b/examples/stall_model.jl index 78fb28fe..a0ee1079 100644 --- a/examples/stall_model.jl +++ b/examples/stall_model.jl @@ -34,9 +34,8 @@ for row in eachrow(df) end # Create wing geometry -# Using REFINE grouping method: n_groups should equal number of unrefined panels (18 sections = 18 panels) -n_groups = length(rib_list) - 1 -CAD_wing = Wing(n_panels; spanwise_distribution, n_groups, grouping_method=REFINE) +# 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]) end @@ -123,7 +122,7 @@ PLOT && plot_polars( angle_of_attack=0, side_slip=0, v_a=10, - title="tutorial_testing_stall_model_n_panels_$(n_panels)_distribution_$(spanwise_distribution)_grouping_$(CAD_wing.grouping_method)", + title="tutorial_testing_stall_model_n_panels_$(n_panels)_distribution_$(spanwise_distribution)_unrefined_$(CAD_wing.n_unrefined_sections)", data_type=".pdf", save_path=joinpath(save_folder, "polars"), is_save=true, diff --git a/ext/VortexStepMethodMakieExt.jl b/ext/VortexStepMethodMakieExt.jl index 203e7e1b..918402a9 100644 --- a/ext/VortexStepMethodMakieExt.jl +++ b/ext/VortexStepMethodMakieExt.jl @@ -310,8 +310,8 @@ function plot_line_segment_makie!(ax, segment, color, label; width=3) # Plot arrow dir = segment[2] - segment[1] - arrows!(ax, [Point3f(segment[1])], [Point3f(dir)]; - color=color, arrowsize=0.1) + arrows3d!(ax, [Point3f(segment[1])], [Point3f(dir)]; + color=color, shaftradius=0.01, tipradius=0.03, tiplength=0.1) end """ @@ -370,7 +370,7 @@ Create a 3D Makie plot of wing geometry including panels and filaments. - `zoom`: zoom factor (default: 1.8) """ function create_geometry_plot_makie(body_aero::BodyAerodynamics, title, - view_elevation, view_azimuth; zoom=1.8) + view_elevation, view_azimuth; zoom=0.5) panels = body_aero.panels va = isa(body_aero.va, Tuple) ? body_aero.va[1] : body_aero.va diff --git a/src/VortexStepMethod.jl b/src/VortexStepMethod.jl index 8c1a407a..fa2b9c70 100644 --- a/src/VortexStepMethod.jl +++ b/src/VortexStepMethod.jl @@ -142,11 +142,14 @@ end """ PanelGroupingMethod EQUAL_SIZE REFINE -Enumeration of methods for grouping panels. +**DEPRECATED**: This enum is deprecated and no longer used. +Grouping is now automatically handled via unrefined section mapping. + +Enumeration of methods for grouping panels (legacy). # Elements -- EQUAL_SIZE: Divide panels into equally-sized sequential groups -- REFINE: Group refined panels back to their original unrefined section +- EQUAL_SIZE: (Deprecated) Divide panels into equally-sized sequential groups +- REFINE: (Deprecated) Group refined panels back to their original unrefined section """ @enum PanelGroupingMethod EQUAL_SIZE REFINE diff --git a/src/body_aerodynamics.jl b/src/body_aerodynamics.jl index 97803526..1a0ae941 100644 --- a/src/body_aerodynamics.jl +++ b/src/body_aerodynamics.jl @@ -4,11 +4,12 @@ Main structure for calculating aerodynamic properties of bodies. Use the constructor to initialize. # Fields -- panels::Vector{Panel}: Vector of [Panel](@ref) structs +- panels::Vector{Panel}: Vector of refined [Panel](@ref) structs - wings::Vector{Wing}: A vector of wings; a body can have multiple wings +- unrefined::Vector{Panel}: Vector of unrefined panel representatives for aggregated results - `va::MVec3` = zeros(MVec3): A vector of the apparent wind speed, see: [MVec3](@ref) - `omega`::MVec3 = zeros(MVec3): A vector of the turn rates around the kite body axes -- `gamma_distribution`=zeros(Float64, P): A vector of the circulation +- `gamma_distribution`=zeros(Float64, P): A vector of the circulation of the velocity field; Length: Number of segments. [m²/s] - `alpha_uncorrected`=zeros(Float64, P): angles of attack per panel - `alpha_corrected`=zeros(Float64, P): corrected angles of attack per panel @@ -24,7 +25,7 @@ Main structure for calculating aerodynamic properties of bodies. Use the constru @with_kw mutable struct BodyAerodynamics{P} panels::Vector{Panel} wings::Vector{Wing} - groups::Vector{Panel} = Panel[] + unrefined::Vector{Panel} = Panel[] _va::MVec3 = zeros(MVec3) omega::MVec3 = zeros(MVec3) gamma_distribution::MVector{P, Float64} = zeros(P) @@ -74,7 +75,7 @@ function BodyAerodynamics( ) where T <: AbstractWing # Initialize panels panels = Panel[] - n_groups = 0 + n_unrefined_total = 0 for wing in wings for section in wing.sections section.LE_point .-= kite_body_origin @@ -94,14 +95,14 @@ function BodyAerodynamics( push!(panels, panel) end - # Count total groups - n_groups += wing.n_groups + # Count total unrefined panels (sections - 1) + n_unrefined_total += (wing.n_unrefined_sections - 1) end - # Initialize groups (unrefined panel representatives) - groups = [Panel() for _ in 1:n_groups] + # Initialize unrefined panels (representatives for unrefined sections) + unrefined = [Panel() for _ in 1:n_unrefined_total] - body_aero = BodyAerodynamics{length(panels)}(; panels, wings, groups) + body_aero = BodyAerodynamics{length(panels)}(; panels, wings, unrefined) reinit!(body_aero; va, omega) return body_aero end diff --git a/src/obj_geometry.jl b/src/obj_geometry.jl index dcf2a2e3..e074a402 100644 --- a/src/obj_geometry.jl +++ b/src/obj_geometry.jl @@ -422,12 +422,35 @@ group_deform!(wing, deg2rad.([5, 10, 5, 0]), deg2rad.([-5, 0, -5, 0])) function ObjWing( obj_path, dat_path; crease_frac=0.9, wind_vel=10., mass=1.0, - n_panels=56, n_sections=n_panels+1, n_groups=4, spanwise_distribution=UNCHANGED, + n_panels=56, n_sections=nothing, n_unrefined_sections=nothing, n_groups=nothing, + spanwise_distribution=LINEAR, spanwise_direction=[0.0, 1.0, 0.0], remove_nan=true, align_to_principal=false, alpha_range=deg2rad.(-5:1:20), delta_range=deg2rad.(-5:1:20), prn=true, - interp_steps=n_sections, grouping_method::PanelGroupingMethod=EQUAL_SIZE + interp_steps=n_panels+1, grouping_method::PanelGroupingMethod=EQUAL_SIZE ) - !(n_groups == 0 || n_panels % n_groups == 0) && throw(ArgumentError("Number of panels should be divisible by number of groups")) + # Handle deprecated parameters + if !isnothing(n_groups) + if !isnothing(n_unrefined_sections) + error("Cannot specify both n_groups and n_unrefined_sections. Use n_unrefined_sections only.") + end + @warn "Parameter n_groups is deprecated. Use n_unrefined_sections instead." maxlog=1 + n_unrefined_sections = n_groups + end + + if !isnothing(n_sections) + @warn "Parameter n_sections is deprecated. It is now always n_panels+1 for refined sections. Use n_unrefined_sections to control initial sections." maxlog=1 + end + + if grouping_method != EQUAL_SIZE + @warn "Parameter grouping_method is deprecated and ignored. Grouping is now always by unrefined sections." maxlog=1 + end + + # Set default: evenly spaced unrefined sections including both tips + if isnothing(n_unrefined_sections) + # Default to having same number of unrefined sections as refined (no refinement) + n_unrefined_sections = n_panels + 1 + end + !isapprox(spanwise_direction, [0.0, 1.0, 0.0]) && throw(ArgumentError("Spanwise direction has to be [0.0, 1.0, 0.0], not $spanwise_direction")) # Load or create polars @@ -472,29 +495,33 @@ function ObjWing( any(isnan.(cm_matrix)) && interpolate_matrix_nans!(cm_matrix; prn) end - # Create sections + # Create unrefined sections (evenly spaced including both tips) sections = Section[] - refined_sections = Section[] - non_deformed_sections = Section[] - for gamma in range(-gamma_tip, gamma_tip, n_sections) - aero_data = (collect(alpha_range), collect(delta_range), cl_matrix, cd_matrix, cm_matrix) + aero_data = (collect(alpha_range), collect(delta_range), cl_matrix, cd_matrix, cm_matrix) + for gamma in range(-gamma_tip, gamma_tip, n_unrefined_sections) LE_point = [le_interp[i](gamma) for i in 1:3] TE_point = [te_interp[i](gamma) for i in 1:3] push!(sections, Section(LE_point, TE_point, POLAR_MATRICES, aero_data)) - push!(refined_sections, Section(LE_point, TE_point, POLAR_MATRICES, aero_data)) - push!(non_deformed_sections, Section(LE_point, TE_point, POLAR_MATRICES, aero_data)) end + # Initialize refined_sections (will be populated by reinit!) + refined_sections = [Section() for _ in 1:(n_panels+1)] + panel_props = PanelProperties{n_panels}() cache = [PreallocationTools.LazyBufferCache()] - Wing(n_panels, n_groups, spanwise_distribution, panel_props, MVec3(spanwise_direction), + wing = Wing(n_panels, Int16(n_unrefined_sections), spanwise_distribution, panel_props, MVec3(spanwise_direction), sections, refined_sections, remove_nan, - grouping_method, Int16[], - non_deformed_sections, zeros(n_panels), zeros(n_panels), + Int16[], + Section[], zeros(n_panels), zeros(n_panels), mass, gamma_tip, inertia_tensor, T_cad_body, R_cad_body, radius, le_interp, te_interp, area_interp, cache) + # Refine mesh and update panel properties + reinit!(wing) + + wing + catch e if e isa BoundsError @error "Delete $cl_polar_path, $cd_polar_path and $cm_polar_path and try again." diff --git a/src/solver.jl b/src/solver.jl index e273929c..eed0cd4e 100644 --- a/src/solver.jl +++ b/src/solver.jl @@ -22,6 +22,12 @@ Struct for storing the solution of the [solve!](@ref) function. Must contain all - `moment_coeffs`::MVec3: Aerodynamic moment coefficients [CMx, CMy, CMz] [-] - `moment_dist`::Vector{Float64}: Pitching moments around the spanwise vector of each panel. [Nm] - `moment_coeff_dist`::Vector{Float64}: Pitching moment coefficient around the spanwise vector of each panel. [-] +- `unrefined_moment_dist`::MVector{G, Float64}: Aggregated moments for unrefined sections [Nm] +- `unrefined_moment_coeff_dist`::MVector{G, Float64}: Aggregated moment coefficients for unrefined sections [-] +- `cl_unrefined_array`::MVector{G, Float64}: Averaged lift coefficients for unrefined sections [-] +- `cd_unrefined_array`::MVector{G, Float64}: Averaged drag coefficients for unrefined sections [-] +- `cm_unrefined_array`::MVector{G, Float64}: Averaged moment coefficients for unrefined sections [-] +- `alpha_unrefined_array`::MVector{G, Float64}: Averaged angles of attack for unrefined sections [rad] - `solver_status`::SolverStatus: enum, see [SolverStatus](@ref) """ @with_kw mutable struct VSMSolution{P,G} @@ -49,12 +55,12 @@ Struct for storing the solution of the [solve!](@ref) function. Must contain all moment_coeffs::MVec3 = zeros(MVec3) moment_dist::MVector{P, Float64} = zeros(P) moment_coeff_dist::MVector{P, Float64} = zeros(P) - group_moment_dist::MVector{G, Float64} = zeros(G) - group_moment_coeff_dist::MVector{G, Float64} = zeros(G) - cl_group_array::MVector{G, Float64} = zeros(G) - cd_group_array::MVector{G, Float64} = zeros(G) - cm_group_array::MVector{G, Float64} = zeros(G) - alpha_group_array::MVector{G, Float64} = zeros(G) + unrefined_moment_dist::MVector{G, Float64} = zeros(G) + unrefined_moment_coeff_dist::MVector{G, Float64} = zeros(G) + cl_unrefined_array::MVector{G, Float64} = zeros(G) + cd_unrefined_array::MVector{G, Float64} = zeros(G) + cm_unrefined_array::MVector{G, Float64} = zeros(G) + alpha_unrefined_array::MVector{G, Float64} = zeros(G) solver_status::SolverStatus = FAILURE end @@ -138,7 +144,7 @@ end function Solver(body_aero; kwargs...) P = length(body_aero.panels) - G = sum([wing.n_groups for wing in body_aero.wings]) + G = sum([(wing.n_unrefined_sections - 1) for wing in body_aero.wings]) return Solver{P,G}(; kwargs...) end @@ -298,124 +304,79 @@ function solve!(solver::Solver, body_aero::BodyAerodynamics, gamma_distribution= moment_coeff_dist[i] = moment_dist[i] / (q_inf * projected_area) end - # Only compute group moments if there are groups - if length(solver.sol.group_moment_dist) > 0 - group_moment_dist = solver.sol.group_moment_dist - group_moment_coeff_dist = solver.sol.group_moment_coeff_dist - cl_group_array = solver.sol.cl_group_array - cd_group_array = solver.sol.cd_group_array - cm_group_array = solver.sol.cm_group_array - alpha_group_array = solver.sol.alpha_group_array - group_moment_dist .= 0.0 - group_moment_coeff_dist .= 0.0 - cl_group_array .= 0.0 - cd_group_array .= 0.0 - cm_group_array .= 0.0 - alpha_group_array .= 0.0 + # Only compute unrefined arrays if there are unrefined sections + if length(solver.sol.unrefined_moment_dist) > 0 + unrefined_moment_dist = solver.sol.unrefined_moment_dist + unrefined_moment_coeff_dist = solver.sol.unrefined_moment_coeff_dist + cl_unrefined_array = solver.sol.cl_unrefined_array + cd_unrefined_array = solver.sol.cd_unrefined_array + cm_unrefined_array = solver.sol.cm_unrefined_array + alpha_unrefined_array = solver.sol.alpha_unrefined_array + unrefined_moment_dist .= 0.0 + unrefined_moment_coeff_dist .= 0.0 + cl_unrefined_array .= 0.0 + cd_unrefined_array .= 0.0 + cm_unrefined_array .= 0.0 + alpha_unrefined_array .= 0.0 panel_idx = 1 - group_idx = 1 + unrefined_idx = 1 for wing in body_aero.wings - if wing.n_groups > 0 - if wing.grouping_method == EQUAL_SIZE - # Original method: divide panels into equally-sized sequential groups - panels_per_group = wing.n_panels ÷ wing.n_groups - for _ in 1:wing.n_groups - panel_count = 0 - group_panel = body_aero.groups[group_idx] - # Zero out accumulated fields - group_panel.x_airf .= 0.0 - group_panel.y_airf .= 0.0 - group_panel.z_airf .= 0.0 - group_panel.va .= 0.0 - group_panel.chord = 0.0 - group_panel.width = 0.0 - for _ in 1:panels_per_group - panel = body_aero.panels[panel_idx] - group_moment_dist[group_idx] += moment_dist[panel_idx] - group_moment_coeff_dist[group_idx] += moment_coeff_dist[panel_idx] - cl_group_array[group_idx] += solver.sol.cl_array[panel_idx] - cd_group_array[group_idx] += solver.sol.cd_array[panel_idx] - cm_group_array[group_idx] += solver.sol.cm_array[panel_idx] - alpha_group_array[group_idx] += solver.sol.alpha_array[panel_idx] - # Accumulate geometry for averaging - group_panel.x_airf .+= panel.x_airf - group_panel.y_airf .+= panel.y_airf - group_panel.z_airf .+= panel.z_airf - group_panel.va .+= panel.va - group_panel.chord += panel.chord - group_panel.width += panel.width - panel_idx += 1 - panel_count += 1 - end - # Average the coefficients and geometry over panels in the group - cl_group_array[group_idx] /= panel_count - cd_group_array[group_idx] /= panel_count - cm_group_array[group_idx] /= panel_count - alpha_group_array[group_idx] /= panel_count - group_panel.x_airf ./= panel_count - group_panel.y_airf ./= panel_count - group_panel.z_airf ./= panel_count - group_panel.va ./= panel_count - group_panel.chord /= panel_count - group_idx += 1 - end - elseif wing.grouping_method == REFINE - # REFINE method: group refined panels by their original unrefined section - # Initialize group panels - for i in 1:wing.n_groups - target_group_idx = group_idx + i - 1 - group_panel = body_aero.groups[target_group_idx] - group_panel.x_airf .= 0.0 - group_panel.y_airf .= 0.0 - group_panel.z_airf .= 0.0 - group_panel.va .= 0.0 - group_panel.chord = 0.0 - group_panel.width = 0.0 - end - # First pass: accumulate values - group_panel_counts = zeros(Int, wing.n_groups) - for local_panel_idx in 1:wing.n_panels - panel = body_aero.panels[panel_idx] - original_section_idx = wing.refined_panel_mapping[local_panel_idx] - target_group_idx = group_idx + original_section_idx - 1 - group_panel = body_aero.groups[target_group_idx] - group_moment_dist[target_group_idx] += moment_dist[panel_idx] - group_moment_coeff_dist[target_group_idx] += moment_coeff_dist[panel_idx] - cl_group_array[target_group_idx] += solver.sol.cl_array[panel_idx] - cd_group_array[target_group_idx] += solver.sol.cd_array[panel_idx] - cm_group_array[target_group_idx] += solver.sol.cm_array[panel_idx] - alpha_group_array[target_group_idx] += solver.sol.alpha_array[panel_idx] - # Accumulate geometry - group_panel.x_airf .+= panel.x_airf - group_panel.y_airf .+= panel.y_airf - group_panel.z_airf .+= panel.z_airf - group_panel.va .+= panel.va - group_panel.chord += panel.chord - group_panel.width += panel.width - group_panel_counts[original_section_idx] += 1 - panel_idx += 1 - end - # Second pass: average coefficients and geometry - for i in 1:wing.n_groups - target_group_idx = group_idx + i - 1 - if group_panel_counts[i] > 0 - group_panel = body_aero.groups[target_group_idx] - cl_group_array[target_group_idx] /= group_panel_counts[i] - cd_group_array[target_group_idx] /= group_panel_counts[i] - cm_group_array[target_group_idx] /= group_panel_counts[i] - alpha_group_array[target_group_idx] /= group_panel_counts[i] - group_panel.x_airf ./= group_panel_counts[i] - group_panel.y_airf ./= group_panel_counts[i] - group_panel.z_airf ./= group_panel_counts[i] - group_panel.va ./= group_panel_counts[i] - group_panel.chord /= group_panel_counts[i] - group_panel.width /= group_panel_counts[i] - end + n_unrefined_panels = wing.n_unrefined_sections - 1 + if n_unrefined_panels > 0 + # Initialize unrefined panels + for i in 1:n_unrefined_panels + target_unrefined_idx = unrefined_idx + i - 1 + unrefined_panel = body_aero.unrefined[target_unrefined_idx] + unrefined_panel.x_airf .= 0.0 + unrefined_panel.y_airf .= 0.0 + unrefined_panel.z_airf .= 0.0 + unrefined_panel.va .= 0.0 + unrefined_panel.chord = 0.0 + unrefined_panel.width = 0.0 + end + # Accumulate values from refined panels + unrefined_panel_counts = zeros(Int, n_unrefined_panels) + for local_panel_idx in 1:wing.n_panels + panel = body_aero.panels[panel_idx] + original_panel_idx = wing.refined_panel_mapping[local_panel_idx] + target_unrefined_idx = unrefined_idx + original_panel_idx - 1 + unrefined_panel = body_aero.unrefined[target_unrefined_idx] + unrefined_moment_dist[target_unrefined_idx] += moment_dist[panel_idx] + unrefined_moment_coeff_dist[target_unrefined_idx] += moment_coeff_dist[panel_idx] + cl_unrefined_array[target_unrefined_idx] += solver.sol.cl_array[panel_idx] + cd_unrefined_array[target_unrefined_idx] += solver.sol.cd_array[panel_idx] + cm_unrefined_array[target_unrefined_idx] += solver.sol.cm_array[panel_idx] + alpha_unrefined_array[target_unrefined_idx] += solver.sol.alpha_array[panel_idx] + # Accumulate geometry + unrefined_panel.x_airf .+= panel.x_airf + unrefined_panel.y_airf .+= panel.y_airf + unrefined_panel.z_airf .+= panel.z_airf + unrefined_panel.va .+= panel.va + unrefined_panel.chord += panel.chord + unrefined_panel.width += panel.width + unrefined_panel_counts[original_panel_idx] += 1 + panel_idx += 1 + end + # Average coefficients and geometry + for i in 1:n_unrefined_panels + target_unrefined_idx = unrefined_idx + i - 1 + if unrefined_panel_counts[i] > 0 + unrefined_panel = body_aero.unrefined[target_unrefined_idx] + cl_unrefined_array[target_unrefined_idx] /= unrefined_panel_counts[i] + cd_unrefined_array[target_unrefined_idx] /= unrefined_panel_counts[i] + cm_unrefined_array[target_unrefined_idx] /= unrefined_panel_counts[i] + alpha_unrefined_array[target_unrefined_idx] /= unrefined_panel_counts[i] + unrefined_panel.x_airf ./= unrefined_panel_counts[i] + unrefined_panel.y_airf ./= unrefined_panel_counts[i] + unrefined_panel.z_airf ./= unrefined_panel_counts[i] + unrefined_panel.va ./= unrefined_panel_counts[i] + unrefined_panel.chord /= unrefined_panel_counts[i] + unrefined_panel.width /= unrefined_panel_counts[i] end - group_idx += wing.n_groups end + unrefined_idx += n_unrefined_panels else - # Skip panels for wings with n_groups=0 + # Skip panels for wings with no unrefined sections panel_idx += wing.n_panels end end diff --git a/src/wing_geometry.jl b/src/wing_geometry.jl index 83889eff..ae7bcf46 100644 --- a/src/wing_geometry.jl +++ b/src/wing_geometry.jl @@ -196,7 +196,7 @@ Represents a wing composed of multiple sections with aerodynamic properties. # Core Fields (all wings) - `n_panels::Int16`: Number of panels in aerodynamic mesh -- `n_groups::Int16`: Number of panel groups +- `n_unrefined_sections::Int16`: Number of unrefined sections (sections before mesh refinement) - `spanwise_distribution`::PanelDistribution: [PanelDistribution](@ref) - `spanwise_direction::MVec3`: Wing span direction vector - `sections::Vector{Section}`: Vector of wing sections, see: [Section](@ref) @@ -223,7 +223,7 @@ Represents a wing composed of multiple sections with aerodynamic properties. """ mutable struct Wing <: AbstractWing n_panels::Int16 - n_groups::Int16 + n_unrefined_sections::Int16 spanwise_distribution::PanelDistribution panel_props::PanelProperties spanwise_direction::MVec3 @@ -232,7 +232,6 @@ mutable struct Wing <: AbstractWing remove_nan::Bool # Grouping - grouping_method::PanelGroupingMethod refined_panel_mapping::Vector{Int16} # Maps each refined panel to its original unrefined section index # Deformation fields @@ -255,7 +254,8 @@ end """ Wing(n_panels::Int; - n_groups=n_panels, + n_unrefined_sections=nothing, + n_groups=nothing, spanwise_distribution::PanelDistribution=LINEAR, spanwise_direction::PosVector=MVec3([0.0, 1.0, 0.0]), remove_nan::Bool=true, @@ -266,32 +266,46 @@ and refined sections as empty arrays. Creates a basic wing suitable for YAML-bas # Parameters - `n_panels::Int`: Number of panels in aerodynamic mesh -- `n_groups::Int`: Number of panel groups in aerodynamic mesh +- `n_unrefined_sections::Int`: Number of unrefined sections (inferred from added sections for YAML wings) +- `n_groups::Int`: DEPRECATED - use n_unrefined_sections instead - `spanwise_distribution`::PanelDistribution = LINEAR: [PanelDistribution](@ref) - `spanwise_direction::MVec3` = MVec3([0.0, 1.0, 0.0]): Wing span direction vector - `remove_nan::Bool`: Wether to remove the NaNs from interpolations or not -- `grouping_method::PanelGroupingMethod` = EQUAL_SIZE: Method for grouping panels (EQUAL_SIZE or REFINE) +- `grouping_method::PanelGroupingMethod` = EQUAL_SIZE: DEPRECATED - grouping is now always by unrefined sections """ function Wing(n_panels::Int; - n_groups = n_panels, + n_unrefined_sections=nothing, + n_groups=nothing, spanwise_distribution::PanelDistribution=LINEAR, spanwise_direction::PosVector=MVec3([0.0, 1.0, 0.0]), remove_nan=true, grouping_method::PanelGroupingMethod=EQUAL_SIZE) - # Validate grouping parameters - if grouping_method == EQUAL_SIZE - !(n_groups == 0 || n_panels % n_groups == 0) && throw(ArgumentError("With EQUAL_SIZE grouping, number of panels should be divisible by number of groups")) + + # Handle deprecated parameters + if !isnothing(n_groups) + if !isnothing(n_unrefined_sections) + error("Cannot specify both n_groups and n_unrefined_sections. Use n_unrefined_sections only.") + end + @warn "Parameter n_groups is deprecated. Use n_unrefined_sections instead." maxlog=1 + n_unrefined_sections = n_groups + end + + if grouping_method != EQUAL_SIZE + @warn "Parameter grouping_method is deprecated and ignored. Grouping is now always by unrefined sections." maxlog=1 end - # Note: For REFINE grouping, validation happens after refinement when we know the number of unrefined sections + + # For YAML wings, n_unrefined_sections will be set when sections are added + # Set to 0 as placeholder for now + n_unrefined_sections_value = isnothing(n_unrefined_sections) ? Int16(0) : Int16(n_unrefined_sections) panel_props = PanelProperties{n_panels}() # Initialize with default/empty values for optional fields Wing( - n_panels, n_groups, spanwise_distribution, panel_props, spanwise_direction, + n_panels, n_unrefined_sections_value, spanwise_distribution, panel_props, spanwise_direction, Section[], Section[], remove_nan, # Grouping - grouping_method, Int16[], + Int16[], # Deformation fields Section[], zeros(n_panels), zeros(n_panels), # Physical properties (defaults for non-OBJ wings) @@ -679,17 +693,8 @@ function refine_aerodynamic_mesh!(wing::AbstractWing; recompute_mapping=true, so # Compute panel mapping by finding closest unrefined panel for each refined panel recompute_mapping && compute_refined_panel_mapping!(wing) - # Validate REFINE grouping method - if wing.grouping_method == REFINE && wing.n_groups > 0 - n_unrefined_panels = length(wing.sections) - 1 - if wing.n_groups != n_unrefined_panels - throw(ArgumentError( - "With REFINE grouping method, n_groups ($(wing.n_groups)) must equal " * - "the number of unrefined panels ($n_unrefined_panels). " * - "The wing has $(length(wing.sections)) unrefined sections, forming $n_unrefined_panels panels." - )) - end - end + # Update n_unrefined_sections based on actual sections + wing.n_unrefined_sections = Int16(length(wing.sections)) # Create/update non_deformed_sections to match refined_sections update_non_deformed_sections!(wing) diff --git a/src/yaml_geometry.jl b/src/yaml_geometry.jl index 098f5c88..a24492e2 100644 --- a/src/yaml_geometry.jl +++ b/src/yaml_geometry.jl @@ -184,16 +184,33 @@ wing = Wing("wing_geometry.yaml"; n_panels=30, n_groups=2, prn=true) function Wing( geometry_file::String; n_panels=20, - n_groups=1, + n_unrefined_sections=nothing, + n_groups=nothing, spanwise_distribution=LINEAR, spanwise_direction=[0.0, 1.0, 0.0], remove_nan=true, prn=false, grouping_method::PanelGroupingMethod=EQUAL_SIZE ) - !(n_groups == 0 || n_panels % n_groups == 0) && throw(ArgumentError("Number of panels should be divisible by number of groups")) + # Handle deprecated parameters + if !isnothing(n_groups) + if !isnothing(n_unrefined_sections) + error("Cannot specify both n_groups and n_unrefined_sections. Use n_unrefined_sections only.") + end + @warn "Parameter n_groups is deprecated. For YAML wings, n_unrefined_sections is inferred from added sections." maxlog=1 + end + + if grouping_method != EQUAL_SIZE + @warn "Parameter grouping_method is deprecated and ignored. Grouping is now always by unrefined sections." maxlog=1 + end + + # For YAML wings, n_unrefined_sections is inferred from the number of sections added + if !isnothing(n_unrefined_sections) + @warn "For YAML wings, n_unrefined_sections is automatically inferred from the sections in the geometry file. The parameter is ignored." maxlog=1 + end + !isapprox(spanwise_direction, [0.0, 1.0, 0.0]) && throw(ArgumentError("Spanwise direction has to be [0.0, 1.0, 0.0], not $spanwise_direction")) - + prn && @info "Reading YAML wing configuration from $geometry_file" # Load YAML file following Uwe's suggestion @@ -237,12 +254,11 @@ function Wing( end # Create Wing using the standard constructor + # n_unrefined_sections will be set automatically after sections are added wing = Wing(n_panels; - n_groups=n_groups, spanwise_distribution=spanwise_distribution, spanwise_direction=MVec3(spanwise_direction), - remove_nan=remove_nan, - grouping_method=grouping_method + remove_nan=remove_nan ) # Parse sections and populate wing diff --git a/test/body_aerodynamics/complete_settings.yaml b/test/body_aerodynamics/complete_settings.yaml index a40ff608..214f7c30 100644 --- a/test/body_aerodynamics/complete_settings.yaml +++ b/test/body_aerodynamics/complete_settings.yaml @@ -2,7 +2,6 @@ wings: - name: "body_aero_test_wing" geometry_file: "test/body_aerodynamics/test_wing.yaml" n_panels: 4 - n_groups: 2 spanwise_panel_distribution: COSINE spanwise_direction: [0.0, 1.0, 0.0] remove_nan: true diff --git a/test/ram_geometry/test_kite_geometry.jl b/test/ram_geometry/test_kite_geometry.jl index 4eb07823..c4d35500 100644 --- a/test/ram_geometry/test_kite_geometry.jl +++ b/test/ram_geometry/test_kite_geometry.jl @@ -224,7 +224,7 @@ using Serialization @testset "First and Last Section Deformation with group_deform!" begin # Create an ObjWing with a small number of panels and groups wing = ObjWing(test_obj_path, test_dat_path; - n_panels=4, n_groups=2, remove_nan=true) + n_panels=4, remove_nan=true) # Store original TE points from all refined_sections # Wing has n_panels+1 sections (5 sections for 4 panels) diff --git a/test/solver/solver_settings.yaml b/test/solver/solver_settings.yaml index 689f915a..142c0c1f 100644 --- a/test/solver/solver_settings.yaml +++ b/test/solver/solver_settings.yaml @@ -2,7 +2,6 @@ wings: - name: "solver_test_wing" geometry_file: "test/solver/solver_test_wing.yaml" n_panels: 4 - n_groups: 2 spanwise_panel_distribution: COSINE spanwise_direction: [0.0, 1.0, 0.0] remove_nan: true diff --git a/test/solver/test_group_coefficients.jl b/test/solver/test_group_coefficients.jl index ede46b2a..6bc6745e 100644 --- a/test/solver/test_group_coefficients.jl +++ b/test/solver/test_group_coefficients.jl @@ -2,23 +2,20 @@ using VortexStepMethod using LinearAlgebra using Test -@testset "Group Coefficient Arrays Tests" begin - @testset "Group coefficients with EQUAL_SIZE method" begin - # Create a simple wing with groups +@testset "Unrefined Coefficient Arrays Tests" begin + @testset "Unrefined coefficients aggregation" begin + # Create a simple wing with unrefined sections n_panels = 20 - n_groups = 4 + n_unrefined_sections = 5 # This gives 4 unrefined panels # Create a test wing settings file settings_file = create_temp_wing_settings("solver", "solver_test_wing.yaml"; alpha=5.0, beta=0.0, wind_speed=10.0) try - # Modify settings to use specific panel/group configuration + # Modify settings to use specific panel configuration settings = VSMSettings(settings_file) settings.wings[1].n_panels = n_panels - settings.wings[1].n_groups = n_groups - settings.wings[1].grouping_method = EQUAL_SIZE settings.solver_settings.n_panels = n_panels - settings.solver_settings.n_groups = n_groups # Create wing and solver wing = Wing(settings) @@ -30,106 +27,75 @@ using Test set_va!(body_aero, va) sol = solve!(solver, body_aero) - # Test 1: Group arrays exist and have correct size - @test length(sol.cl_group_array) == n_groups - @test length(sol.cd_group_array) == n_groups - @test length(sol.cm_group_array) == n_groups - - # Test 2: Group arrays are not all zeros (solver computed them) - @test !all(sol.cl_group_array .== 0.0) - @test !all(sol.cd_group_array .== 0.0) - - # Test 3: Verify group coefficients are averages of panel coefficients - panels_per_group = n_panels ÷ n_groups - for group_idx in 1:n_groups - panel_start = (group_idx - 1) * panels_per_group + 1 - panel_end = group_idx * panels_per_group - - # Calculate expected average from panel coefficients - expected_cl = sum(sol.cl_array[panel_start:panel_end]) / panels_per_group - expected_cd = sum(sol.cd_array[panel_start:panel_end]) / panels_per_group - expected_cm = sum(sol.cm_array[panel_start:panel_end]) / panels_per_group - - # Check if group coefficients match expected averages - # Handle NaN values that can occur in INVISCID models - if isnan(expected_cl) - @test isnan(sol.cl_group_array[group_idx]) - else - @test isapprox(sol.cl_group_array[group_idx], expected_cl, rtol=1e-10) - end - if isnan(expected_cd) - @test isnan(sol.cd_group_array[group_idx]) - else - @test isapprox(sol.cd_group_array[group_idx], expected_cd, rtol=1e-10) - end - if isnan(expected_cm) - @test isnan(sol.cm_group_array[group_idx]) - else - @test isapprox(sol.cm_group_array[group_idx], expected_cm, rtol=1e-10) - end - end - - # Test 4: Verify physical consistency (lift coefficients should be positive at positive AoA) - # Skip test if values are NaN - if !any(isnan.(sol.cl_group_array)) - @test all(sol.cl_group_array .> 0.0) - end - - finally - rm(settings_file; force=true) - end - end + n_unrefined_panels = wing.n_unrefined_sections - 1 - @testset "Group coefficients with n_groups=0 (no grouping)" begin - # Create a wing with no groups - n_panels = 20 - n_groups = 0 + # Test 1: Unrefined arrays exist and have correct size + @test length(sol.cl_unrefined_array) == n_unrefined_panels + @test length(sol.cd_unrefined_array) == n_unrefined_panels + @test length(sol.cm_unrefined_array) == n_unrefined_panels - settings_file = create_temp_wing_settings("solver", "solver_test_wing.yaml"; alpha=5.0, beta=0.0, wind_speed=10.0) + # Test 2: Unrefined arrays are not all zeros (solver computed them) + @test !all(sol.cl_unrefined_array .== 0.0) + @test !all(sol.cd_unrefined_array .== 0.0) - try - settings = VSMSettings(settings_file) - settings.wings[1].n_panels = n_panels - settings.wings[1].n_groups = n_groups - settings.solver_settings.n_panels = n_panels - settings.solver_settings.n_groups = n_groups + # Test 3: Verify unrefined coefficients are aggregated from refined panels + # using refined_panel_mapping + for unrefined_idx in 1:n_unrefined_panels + # Find all refined panels that map to this unrefined panel + refined_panel_indices = findall(x -> x == unrefined_idx, wing.refined_panel_mapping) - wing = Wing(settings) - body_aero = BodyAerodynamics([wing]) - solver = Solver(body_aero, settings) + if !isempty(refined_panel_indices) + # Calculate expected average from refined panel coefficients + expected_cl = sum(sol.cl_array[refined_panel_indices]) / length(refined_panel_indices) + expected_cd = sum(sol.cd_array[refined_panel_indices]) / length(refined_panel_indices) + expected_cm = sum(sol.cm_array[refined_panel_indices]) / length(refined_panel_indices) - va = [10.0, 0.0, 0.0] - set_va!(body_aero, va) - sol = solve!(solver, body_aero) + # Check if unrefined coefficients match expected averages + # Handle NaN values that can occur in INVISCID models + if isnan(expected_cl) + @test isnan(sol.cl_unrefined_array[unrefined_idx]) + else + @test isapprox(sol.cl_unrefined_array[unrefined_idx], expected_cl, rtol=1e-10) + end + if isnan(expected_cd) + @test isnan(sol.cd_unrefined_array[unrefined_idx]) + else + @test isapprox(sol.cd_unrefined_array[unrefined_idx], expected_cd, rtol=1e-10) + end + if isnan(expected_cm) + @test isnan(sol.cm_unrefined_array[unrefined_idx]) + else + @test isapprox(sol.cm_unrefined_array[unrefined_idx], expected_cm, rtol=1e-10) + end + end + end - # Test: Group arrays should be empty when n_groups=0 - @test length(sol.cl_group_array) == 0 - @test length(sol.cd_group_array) == 0 - @test length(sol.cm_group_array) == 0 + # Test 4: Verify physical consistency (lift coefficients should be positive at positive AoA) + # Skip test if values are NaN + if !any(isnan.(sol.cl_unrefined_array)) + @test all(sol.cl_unrefined_array .> 0.0) + end finally rm(settings_file; force=true) end end - @testset "Group coefficients with different group sizes" begin - # Test with various panel/group combinations + @testset "Unrefined coefficients with different panel counts" begin + # Test with various panel/section combinations test_cases = [ - (n_panels=40, n_groups=8), - (n_panels=30, n_groups=5), - (n_panels=24, n_groups=6), + (n_panels=40, n_unrefined_expected=21), # From YAML file sections + (n_panels=30, n_unrefined_expected=21), + (n_panels=24, n_unrefined_expected=21), ] - for (n_panels, n_groups) in test_cases + for (n_panels, n_unrefined_expected) in test_cases settings_file = create_temp_wing_settings("solver", "solver_test_wing.yaml"; alpha=5.0, beta=0.0, wind_speed=10.0) try settings = VSMSettings(settings_file) settings.wings[1].n_panels = n_panels - settings.wings[1].n_groups = n_groups - settings.wings[1].grouping_method = EQUAL_SIZE settings.solver_settings.n_panels = n_panels - settings.solver_settings.n_groups = n_groups wing = Wing(settings) body_aero = BodyAerodynamics([wing]) @@ -139,36 +105,38 @@ using Test set_va!(body_aero, va) sol = solve!(solver, body_aero) - # Verify arrays have correct size - @test length(sol.cl_group_array) == n_groups - @test length(sol.cd_group_array) == n_groups - @test length(sol.cm_group_array) == n_groups - - # Verify group coefficients are computed correctly - panels_per_group = n_panels ÷ n_groups - for group_idx in 1:n_groups - panel_start = (group_idx - 1) * panels_per_group + 1 - panel_end = group_idx * panels_per_group - - expected_cl = sum(sol.cl_array[panel_start:panel_end]) / panels_per_group - expected_cd = sum(sol.cd_array[panel_start:panel_end]) / panels_per_group - expected_cm = sum(sol.cm_array[panel_start:panel_end]) / panels_per_group + n_unrefined_panels = wing.n_unrefined_sections - 1 - # Handle NaN for all coefficients - if isnan(expected_cl) - @test isnan(sol.cl_group_array[group_idx]) - else - @test isapprox(sol.cl_group_array[group_idx], expected_cl, rtol=1e-10) - end - if isnan(expected_cd) - @test isnan(sol.cd_group_array[group_idx]) - else - @test isapprox(sol.cd_group_array[group_idx], expected_cd, rtol=1e-10) - end - if isnan(expected_cm) - @test isnan(sol.cm_group_array[group_idx]) - else - @test isapprox(sol.cm_group_array[group_idx], expected_cm, rtol=1e-10) + # Verify arrays have correct size + @test length(sol.cl_unrefined_array) == n_unrefined_panels + @test length(sol.cd_unrefined_array) == n_unrefined_panels + @test length(sol.cm_unrefined_array) == n_unrefined_panels + + # Verify unrefined coefficients are computed correctly using mapping + for unrefined_idx in 1:n_unrefined_panels + refined_panel_indices = findall(x -> x == unrefined_idx, wing.refined_panel_mapping) + + if !isempty(refined_panel_indices) + expected_cl = sum(sol.cl_array[refined_panel_indices]) / length(refined_panel_indices) + expected_cd = sum(sol.cd_array[refined_panel_indices]) / length(refined_panel_indices) + expected_cm = sum(sol.cm_array[refined_panel_indices]) / length(refined_panel_indices) + + # Handle NaN for all coefficients + if isnan(expected_cl) + @test isnan(sol.cl_unrefined_array[unrefined_idx]) + else + @test isapprox(sol.cl_unrefined_array[unrefined_idx], expected_cl, rtol=1e-10) + end + if isnan(expected_cd) + @test isnan(sol.cd_unrefined_array[unrefined_idx]) + else + @test isapprox(sol.cd_unrefined_array[unrefined_idx], expected_cd, rtol=1e-10) + end + if isnan(expected_cm) + @test isnan(sol.cm_unrefined_array[unrefined_idx]) + else + @test isapprox(sol.cm_unrefined_array[unrefined_idx], expected_cm, rtol=1e-10) + end end end diff --git a/test/wing_geometry/test_wing_geometry.jl b/test/wing_geometry/test_wing_geometry.jl index ddb8ae25..05458a64 100644 --- a/test/wing_geometry/test_wing_geometry.jl +++ b/test/wing_geometry/test_wing_geometry.jl @@ -333,14 +333,14 @@ end end end - @testset "REFINE grouping panel mapping" begin + @testset "Refined panel mapping" begin # Test that refined panel mapping actually maps each panel to its closest unrefined panel @testset "LINEAR distribution" begin n_panels = 20 span = 10.0 - wing = Wing(n_panels; spanwise_distribution=LINEAR, n_groups=2, grouping_method=REFINE) + wing = Wing(n_panels; spanwise_distribution=LINEAR) # 3 sections = 2 unrefined panels add_section!(wing, [0.0, span/2, 0.0], [1.0, span/2, 0.0], INVISCID) add_section!(wing, [0.0, 0.0, 0.0], [1.0, 0.0, 0.0], INVISCID) @@ -386,7 +386,7 @@ end n_panels = 30 span = 20.0 - wing = Wing(n_panels; spanwise_distribution=COSINE, n_groups=3, grouping_method=REFINE) + wing = Wing(n_panels; spanwise_distribution=COSINE) # 4 sections = 3 unrefined panels add_section!(wing, [0.0, span/2, 0.0], [1.0, span/2, 0.0], INVISCID) add_section!(wing, [0.0, span/6, 0.0], [1.0, span/6, 0.0], INVISCID) @@ -432,7 +432,7 @@ end @testset "SPLIT_PROVIDED distribution" begin n_panels = 12 - wing = Wing(n_panels; spanwise_distribution=SPLIT_PROVIDED, n_groups=3, grouping_method=REFINE) + wing = Wing(n_panels; spanwise_distribution=SPLIT_PROVIDED) # 4 sections = 3 unrefined panels add_section!(wing, [0.0, 6.0, 0.0], [1.0, 6.0, 0.0], INVISCID) add_section!(wing, [0.0, 2.0, 0.0], [1.0, 2.0, 0.0], INVISCID) @@ -475,14 +475,5 @@ end end end - @testset "Validation: n_groups must equal unrefined panels" begin - wing = Wing(20; spanwise_distribution=LINEAR, n_groups=5, grouping_method=REFINE) - add_section!(wing, [0.0, 5.0, 0.0], [1.0, 5.0, 0.0], INVISCID) - add_section!(wing, [0.0, 0.0, 0.0], [1.0, 0.0, 0.0], INVISCID) - add_section!(wing, [0.0, -5.0, 0.0], [1.0, -5.0, 0.0], INVISCID) - - # Should throw error: 5 groups but only 2 unrefined panels - @test_throws ArgumentError refine_aerodynamic_mesh!(wing) - end end end \ No newline at end of file diff --git a/test/yaml_geometry/test_wing_constructor.jl b/test/yaml_geometry/test_wing_constructor.jl index 19ec9869..87a1ab8e 100644 --- a/test/yaml_geometry/test_wing_constructor.jl +++ b/test/yaml_geometry/test_wing_constructor.jl @@ -37,11 +37,11 @@ using Logging # Use the actual YAML file from the test data cp(test_data_path("yaml_geometry", "simple_wing.yaml"), test_yaml_path; force=true) - wing = Wing(test_yaml_path; n_panels=4, n_groups=2) + wing = Wing(test_yaml_path; n_panels=4, # n_groups=2) @test wing isa Wing @test wing.n_panels == 4 - @test wing.n_groups == 2 + @test wing.n_unrefined_sections - 1 == 2 @test wing.spanwise_distribution == LINEAR @test wing.spanwise_direction ≈ [0.0, 1.0, 0.0] @test length(wing.sections) == 2 # simple_wing has 2 sections @@ -72,13 +72,13 @@ using Logging wing = Wing( test_yaml_path; n_panels=8, - n_groups=4, + # n_groups=4, spanwise_distribution=COSINE, remove_nan=false ) @test wing.n_panels == 8 - @test wing.n_groups == 4 + @test wing.n_unrefined_sections - 1 == 4 @test wing.spanwise_distribution == COSINE @test !wing.remove_nan end @@ -150,10 +150,10 @@ wing_airfoils: write(test_yaml_path, yaml_content) # Test invalid n_panels/n_groups combination - @test_throws ArgumentError Wing(test_yaml_path; n_panels=5, n_groups=2) + @test_throws ArgumentError Wing(test_yaml_path; n_panels=5, # n_groups=2) - # Test n_groups=0 (no grouping functionality) - wing_no_groups = Wing(test_yaml_path; n_panels=4, n_groups=0) + # Test # n_groups=0 (no grouping functionality) + wing_no_groups = Wing(test_yaml_path; n_panels=4, # n_groups=0) @test wing_no_groups.n_groups == 0 @test wing_no_groups.n_panels == 4 @@ -190,10 +190,10 @@ wing_airfoils: # Use the actual complex_wing.yaml file cp(test_data_path("yaml_geometry", "complex_wing.yaml"), test_yaml_path; force=true) - wing = Wing(test_yaml_path; n_panels=12, n_groups=3) + wing = Wing(test_yaml_path; n_panels=12, # n_groups=3) @test wing.n_panels == 12 - @test wing.n_groups == 3 + @test wing.n_unrefined_sections - 1 == 3 @test length(wing.sections) == 7 # Test that different airfoil_ids get different polar data @@ -216,7 +216,7 @@ wing_airfoils: settings.wings = [WingSettings( geometry_file=simple_wing_file, n_panels=6, - n_groups=3, + # n_groups=3, spanwise_panel_distribution=COSINE )] @@ -225,7 +225,7 @@ wing_airfoils: @test wing isa Wing @test wing.n_panels == 6 - @test wing.n_groups == 3 + @test wing.n_unrefined_sections - 1 == 3 @test wing.spanwise_distribution == COSINE @test length(wing.sections) == 2 @test wing.sections[1].aero_model == POLAR_VECTORS @@ -238,17 +238,17 @@ wing_airfoils: @test isfile(simple_wing_file) # Test basic Wing construction with shared data - wing = Wing(simple_wing_file; n_panels=4, n_groups=2) + wing = Wing(simple_wing_file; n_panels=4, # n_groups=2) @test wing isa Wing @test wing.n_panels == 4 - @test wing.n_groups == 2 + @test wing.n_unrefined_sections - 1 == 2 @test length(wing.sections) == 2 # Test complex wing construction complex_wing_file = test_data_path("yaml_geometry", "complex_wing.yaml") @test isfile(complex_wing_file) - complex_wing = Wing(complex_wing_file; n_panels=12, n_groups=3) + complex_wing = Wing(complex_wing_file; n_panels=12, # n_groups=3) @test complex_wing isa Wing @test complex_wing.n_panels == 12 @test complex_wing.n_groups == 3 @@ -262,7 +262,7 @@ wing_airfoils: standard_wing_file = simple_wing_file # Use simple_wing as our "standard" @test isfile(standard_wing_file) - standard_wing = Wing(standard_wing_file; n_panels=2, n_groups=1) + standard_wing = Wing(standard_wing_file; n_panels=2, # n_groups=1) @test standard_wing isa Wing @test length(standard_wing.sections) == 2 end diff --git a/test/yaml_geometry/test_yaml_wing_deformation.jl b/test/yaml_geometry/test_yaml_wing_deformation.jl index 578528b2..ac51e243 100644 --- a/test/yaml_geometry/test_yaml_wing_deformation.jl +++ b/test/yaml_geometry/test_yaml_wing_deformation.jl @@ -6,7 +6,7 @@ using Test @testset "Simple Wing Deformation" begin # Load existing simple_wing.yaml simple_wing_file = test_data_path("yaml_geometry", "simple_wing.yaml") - wing = Wing(simple_wing_file; n_panels=4, n_groups=2) + wing = Wing(simple_wing_file; n_panels=4, # n_groups=2) body_aero = BodyAerodynamics([wing]) # Store original TE point for comparison @@ -53,7 +53,7 @@ using Test @testset "Complex Wing Deformation" begin # Load existing complex_wing.yaml with multiple sections complex_wing_file = test_data_path("yaml_geometry", "complex_wing.yaml") - wing = Wing(complex_wing_file; n_panels=12, n_groups=3) + wing = Wing(complex_wing_file; n_panels=12, # n_groups=3) body_aero = BodyAerodynamics([wing]) # Store original points for multiple panels @@ -104,7 +104,7 @@ using Test @testset "Multiple Reinit Calls with NTuple aero_data" begin # This test specifically checks the NTuple handling fix simple_wing_file = test_data_path("yaml_geometry", "simple_wing.yaml") - wing = Wing(simple_wing_file; n_panels=4, n_groups=2) + wing = Wing(simple_wing_file; n_panels=4, # n_groups=2) # Verify that sections have NTuple aero_data (for wings with simple polars) # or other valid AeroData types @@ -125,7 +125,7 @@ using Test @testset "Deformation with BodyAerodynamics Reinit" begin # Test that reinit! on BodyAerodynamics properly handles deformed wings simple_wing_file = test_data_path("yaml_geometry", "simple_wing.yaml") - wing = Wing(simple_wing_file; n_panels=4, n_groups=2) + wing = Wing(simple_wing_file; n_panels=4, # n_groups=2) body_aero = BodyAerodynamics([wing]) # Apply deformation @@ -153,7 +153,7 @@ using Test @testset "Edge Cases" begin simple_wing_file = test_data_path("yaml_geometry", "simple_wing.yaml") - wing = Wing(simple_wing_file; n_panels=2, n_groups=1) + wing = Wing(simple_wing_file; n_panels=2, # n_groups=1) body_aero = BodyAerodynamics([wing]) # Test zero deformation From 988b1c91f37fb17158d7b771de1394d0041b1407 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Thu, 4 Dec 2025 14:46:13 +0100 Subject: [PATCH 27/86] Use glmakie --- examples/V3_kite.jl | 2 +- examples/pyramid_model.jl | 2 +- examples/ram_air_kite.jl | 1 + examples/rectangular_wing.jl | 2 +- examples/stall_model.jl | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/examples/V3_kite.jl b/examples/V3_kite.jl index 9f50b6d4..4833c776 100644 --- a/examples/V3_kite.jl +++ b/examples/V3_kite.jl @@ -1,6 +1,6 @@ using LinearAlgebra using VortexStepMethod -using ControlPlots +using GLMakie project_dir = dirname(dirname(pathof(VortexStepMethod))) # Go up one level from src to project root# literature_paths = [ diff --git a/examples/pyramid_model.jl b/examples/pyramid_model.jl index 837e26ef..a67d8bb5 100644 --- a/examples/pyramid_model.jl +++ b/examples/pyramid_model.jl @@ -1,6 +1,6 @@ using LinearAlgebra using VortexStepMethod -using ControlPlots +using GLMakie project_dir = dirname(dirname(pathof(VortexStepMethod))) # Go up one level from src to project root diff --git a/examples/ram_air_kite.jl b/examples/ram_air_kite.jl index bbf1480b..f47e5938 100644 --- a/examples/ram_air_kite.jl +++ b/examples/ram_air_kite.jl @@ -12,6 +12,7 @@ LINEARIZE = false wing = ObjWing( joinpath("data", "ram_air_kite", "ram_air_kite_body.obj"), joinpath("data", "ram_air_kite", "ram_air_kite_foil.dat"); + n_unrefined_sections=4, prn=PRN ) body_aero = BodyAerodynamics([wing];) diff --git a/examples/rectangular_wing.jl b/examples/rectangular_wing.jl index 94dc5aec..360eb5ce 100644 --- a/examples/rectangular_wing.jl +++ b/examples/rectangular_wing.jl @@ -1,5 +1,5 @@ using LinearAlgebra -using ControlPlots +using GLMakie using VortexStepMethod PLOT = true diff --git a/examples/stall_model.jl b/examples/stall_model.jl index a0ee1079..510fe094 100644 --- a/examples/stall_model.jl +++ b/examples/stall_model.jl @@ -1,4 +1,4 @@ -using ControlPlots +using GLMakie using LinearAlgebra using VortexStepMethod From ab1a2822d5b5c07391ca8f85fb64a2e83c814793 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Thu, 4 Dec 2025 14:46:56 +0100 Subject: [PATCH 28/86] Use unrefined segments and no groups --- src/body_aerodynamics.jl | 25 ++++++-- src/settings.jl | 9 ++- src/solver.jl | 28 ++++---- src/wing_geometry.jl | 134 +++++++++++++++++++-------------------- 4 files changed, 104 insertions(+), 92 deletions(-) diff --git a/src/body_aerodynamics.jl b/src/body_aerodynamics.jl index 1a0ae941..e4337c28 100644 --- a/src/body_aerodynamics.jl +++ b/src/body_aerodynamics.jl @@ -96,11 +96,11 @@ function BodyAerodynamics( end # Count total unrefined panels (sections - 1) - n_unrefined_total += (wing.n_unrefined_sections - 1) + n_unrefined_total += max(0, wing.n_unrefined_sections - 1) end # Initialize unrefined panels (representatives for unrefined sections) - unrefined = [Panel() for _ in 1:n_unrefined_total] + unrefined = [Panel() for _ in 1:max(0, n_unrefined_total)] body_aero = BodyAerodynamics{length(panels)}(; panels, wings, unrefined) reinit!(body_aero; va, omega) @@ -160,8 +160,10 @@ function reinit!(body_aero::BodyAerodynamics; # Create panels for i in 1:wing.n_panels - if !isnothing(wing.delta_dist) - delta = wing.delta_dist[i] + if !isnothing(wing.delta_dist) && length(wing.delta_dist) > 0 + # Map refined panel to unrefined section to get delta value + unrefined_idx = wing.refined_panel_mapping[i] + delta = wing.delta_dist[unrefined_idx] else delta = 0.0 end @@ -184,12 +186,23 @@ function reinit!(body_aero::BodyAerodynamics; idx += 1 end end - + + # Resize unrefined vector if needed (after wings are reinitialized and n_unrefined_sections is set) + n_unrefined_total = sum([max(0, wing.n_unrefined_sections - 1) for wing in body_aero.wings]) + if length(body_aero.unrefined) != n_unrefined_total + resize!(body_aero.unrefined, n_unrefined_total) + for i in 1:n_unrefined_total + if !isassigned(body_aero.unrefined, i) + body_aero.unrefined[i] = Panel() + end + end + end + # Initialize rest of the struct body_aero.projected_area = sum(calculate_projected_area, body_aero.wings) calculate_stall_angle_list!(body_aero.stall_angle_list, body_aero.panels) body_aero.alpha_array .= 0.0 - body_aero.v_a_array .= 0.0 + body_aero.v_a_array .= 0.0 body_aero.AIC .= 0.0 set_va!(body_aero, va, omega) return nothing diff --git a/src/settings.jl b/src/settings.jl index ea19b4d1..4010b8d9 100644 --- a/src/settings.jl +++ b/src/settings.jl @@ -79,17 +79,20 @@ function VSMSettings(filename; data_prefix=true) wing.dat_file = wing_data["dat_file"] end wing.n_panels = wing_data["n_panels"] - wing.n_groups = wing_data["n_groups"] + # Handle deprecated n_groups parameter + if haskey(wing_data, "n_groups") + @warn "n_groups in settings file is deprecated and ignored. Use n_unrefined_sections or let it be inferred automatically." maxlog=1 + end wing.spanwise_panel_distribution = eval(Symbol(wing_data["spanwise_panel_distribution"])) wing.spanwise_direction = MVec3(wing_data["spanwise_direction"]) if haskey(wing_data, "grouping_method") - wing.grouping_method = eval(Symbol(wing_data["grouping_method"])) + @warn "grouping_method in settings file is deprecated and ignored." maxlog=1 end wing.remove_nan = wing_data["remove_nan"] push!(vsm_settings.wings, wing) n_panels += wing.n_panels - n_groups += wing.n_groups + # n_unrefined_sections will be set when wing is created/initialized end end diff --git a/src/solver.jl b/src/solver.jl index eed0cd4e..a7137bfa 100644 --- a/src/solver.jl +++ b/src/solver.jl @@ -144,7 +144,7 @@ end function Solver(body_aero; kwargs...) P = length(body_aero.panels) - G = sum([(wing.n_unrefined_sections - 1) for wing in body_aero.wings]) + G = sum([max(0, wing.n_unrefined_sections - 1) for wing in body_aero.wings]) return Solver{P,G}(; kwargs...) end @@ -739,7 +739,7 @@ Compute the Jacobian matrix for a deformable wing around an operating point usin # Returns - `jac`: Jacobian matrix (∂outputs/∂inputs) -- `results`: Output vector at the operating point [Fx, Fy, Fz, Mx, My, Mz, group_moments...] +- `results`: Output vector at the operating point [Fx, Fy, Fz, Mx, My, Mz, unrefined_moments...] # Example ```julia @@ -773,17 +773,17 @@ function linearize(solver::Solver, body_aero::BodyAerodynamics, y::Vector{T}; !(length(body_aero.wings) == 1) && throw(ArgumentError("Linearization only works for a body_aero with one wing")) wing = body_aero.wings[1] - # Validate that theta_idxs and delta_idxs match the number of groups - if !isnothing(theta_idxs) && wing.n_groups > 0 - length(theta_idxs) != wing.n_groups && throw(ArgumentError( - "Length of theta_idxs ($(length(theta_idxs))) must match number of groups ($(wing.n_groups))")) + # Validate that theta_idxs and delta_idxs match the number of unrefined sections + if !isnothing(theta_idxs) && wing.n_unrefined_sections > 0 + length(theta_idxs) != wing.n_unrefined_sections && throw(ArgumentError( + "Length of theta_idxs ($(length(theta_idxs))) must match number of unrefined sections ($(wing.n_unrefined_sections))")) end - if !isnothing(delta_idxs) && wing.n_groups > 0 - length(delta_idxs) != wing.n_groups && throw(ArgumentError( - "Length of delta_idxs ($(length(delta_idxs))) must match number of groups ($(wing.n_groups))")) + if !isnothing(delta_idxs) && wing.n_unrefined_sections > 0 + length(delta_idxs) != wing.n_unrefined_sections && throw(ArgumentError( + "Length of delta_idxs ($(length(delta_idxs))) must match number of unrefined sections ($(wing.n_unrefined_sections))")) end - if wing.n_groups == 0 && (!isnothing(theta_idxs) || !isnothing(delta_idxs)) - throw(ArgumentError("Cannot use theta_idxs or delta_idxs when wing has n_groups=0 (no group functionality)")) + if wing.n_unrefined_sections == 0 && (!isnothing(theta_idxs) || !isnothing(delta_idxs)) + throw(ArgumentError("Cannot use theta_idxs or delta_idxs when wing has no unrefined sections")) end init_va = body_aero.cache[1][body_aero.va] @@ -835,16 +835,16 @@ function linearize(solver::Solver, body_aero::BodyAerodynamics, y::Vector{T}; if !aero_coeffs results[1:3] .= solver.sol.force results[4:6] .= solver.sol.moment - results[7:end] .= solver.sol.group_moment_dist + results[7:end] .= solver.sol.unrefined_moment_dist else results[1:3] .= solver.sol.force_coeffs results[4:6] .= solver.sol.moment_coeffs - results[7:end] .= solver.sol.group_moment_coeff_dist + results[7:end] .= solver.sol.unrefined_moment_coeff_dist end return nothing end - results = zeros(3+3+length(solver.sol.group_moment_dist)) + results = zeros(3+3+length(solver.sol.unrefined_moment_dist)) jac = zeros(length(results), length(y)) backend = AutoFiniteDiff(absstep=1e2solver.atol, relstep=1e2solver.rtol) prep = prepare_jacobian(calc_results!, results, backend, y) diff --git a/src/wing_geometry.jl b/src/wing_geometry.jl index ae7bcf46..7ac9e93c 100644 --- a/src/wing_geometry.jl +++ b/src/wing_geometry.jl @@ -236,8 +236,8 @@ mutable struct Wing <: AbstractWing # Deformation fields non_deformed_sections::Vector{Section} - theta_dist::Vector{Float64} - delta_dist::Vector{Float64} + theta_dist::Vector{Float64} # Length: n_unrefined_sections (section twist angles) + delta_dist::Vector{Float64} # Length: n_unrefined_sections (section TE deflection angles) # Physical properties (OBJ-based wings) mass::Float64 @@ -307,7 +307,7 @@ function Wing(n_panels::Int; # Grouping Int16[], # Deformation fields - Section[], zeros(n_panels), zeros(n_panels), + Section[], zeros(max(0, n_unrefined_sections_value)), zeros(max(0, n_unrefined_sections_value)), # Physical properties (defaults for non-OBJ wings) 0.0, 0.0, zeros(0, 0), zeros(MVec3), Matrix{Float64}(I, 3, 3), 0.0, nothing, nothing, nothing, @@ -346,27 +346,28 @@ end """ group_deform!(wing::Wing, theta_angles=nothing, delta_angles=nothing; smooth=false) -Distribute control angles across wing panels and optionally apply smoothing. +Apply deformation angles directly to unrefined wing sections. For wings that support deformation (OBJ-based wings with non_deformed_sections), this -distributes theta_angles and delta_angles to panel groups and applies deformation. +applies theta_angles and delta_angles directly to unrefined sections and then applies deformation. For wings without deformation support (YAML-based), this is a no-op that only succeeds if both angle inputs are nothing. # Arguments - `wing::Wing`: The wing to deform -- `theta_angles::AbstractVector`: Twist angles in radians for each control group (or nothing) -- `delta_angles::AbstractVector`: Trailing edge deflection angles in radians (or nothing) -- `smooth::Bool`: Whether to apply moving average smoothing +- `theta_angles::AbstractVector`: Twist angles in radians for each unrefined section (or nothing). + Length must be `n_unrefined_sections` +- `delta_angles::AbstractVector`: Trailing edge deflection angles in radians for each unrefined section (or nothing). + Length must be `n_unrefined_sections` +- `smooth::Bool`: DEPRECATED - no longer used. Apply smoothing to input angles if needed. # Algorithm -1. Distributes each control input to its corresponding group of panels -2. Optionally applies moving average smoothing with window based on group size -3. Calls deform! to update wing geometry +1. Copies theta_angles and delta_angles directly to wing.theta_dist and wing.delta_dist +2. Calls deform! to update wing geometry and propagate to refined sections # Errors - Throws `ArgumentError` if wing doesn't support deformation but angles are provided -- Throws `ArgumentError` if panel count is not divisible by number of control inputs +- Throws `ArgumentError` if angle vectors don't match n_unrefined_sections # Returns - `nothing` (modifies wing in-place) @@ -384,47 +385,25 @@ function group_deform!(wing::Wing, theta_angles=nothing, delta_angles=nothing; s end # Validate inputs - !isnothing(theta_angles) && !(wing.n_panels % length(theta_angles) == 0) && - throw(ArgumentError("Number of theta_angles has to be a divisor of number of panels")) - !isnothing(delta_angles) && !(wing.n_panels % length(delta_angles) == 0) && - throw(ArgumentError("Number of delta_angles has to be a divisor of number of panels")) - - n_panels = wing.n_panels - theta_dist = wing.theta_dist - delta_dist = wing.delta_dist - n_angles = isnothing(theta_angles) ? length(delta_angles) : length(theta_angles) - - # Distribute angles to panels - dist_idx = 0 - for angle_idx in 1:n_angles - for _ in 1:(wing.n_panels ÷ n_angles) - dist_idx += 1 - !isnothing(theta_angles) && (theta_dist[dist_idx] = theta_angles[angle_idx]) - !isnothing(delta_angles) && (delta_dist[dist_idx] = delta_angles[angle_idx]) - end - end - @assert (dist_idx == wing.n_panels) - - # Apply smoothing if requested - if smooth - window_size = wing.n_panels ÷ n_angles - if n_panels > window_size - smoothed = wing.cache[1][theta_dist] - - if !isnothing(theta_angles) - smoothed .= theta_dist - for i in (window_size÷2 + 1):(n_panels - window_size÷2) - @views smoothed[i] = mean(theta_dist[(i - window_size÷2):(i + window_size÷2)]) - end - theta_dist .= smoothed + !isnothing(theta_angles) && length(theta_angles) != wing.n_unrefined_sections && + throw(ArgumentError("theta_angles must have length n_unrefined_sections = $(wing.n_unrefined_sections), got $(length(theta_angles))")) + !isnothing(delta_angles) && length(delta_angles) != wing.n_unrefined_sections && + throw(ArgumentError("delta_angles must have length n_unrefined_sections = $(wing.n_unrefined_sections), got $(length(delta_angles))")) + + # Copy angles to theta_dist and delta_dist + !isnothing(theta_angles) && (wing.theta_dist .= theta_angles) + !isnothing(delta_angles) && (wing.delta_dist .= delta_angles) + + # Apply 3-point moving average smoothing if requested + if smooth && wing.n_unrefined_sections > 2 + if !isnothing(theta_angles) + for i in 2:(wing.n_unrefined_sections-1) + wing.theta_dist[i] = (wing.theta_dist[i-1] + wing.theta_dist[i] + wing.theta_dist[i+1]) / 3.0 end - - if !isnothing(delta_angles) - smoothed .= delta_dist - for i in (window_size÷2 + 1):(n_panels - window_size÷2) - @views smoothed[i] = mean(delta_dist[(i - window_size÷2):(i + window_size÷2)]) - end - delta_dist .= smoothed + end + if !isnothing(delta_angles) + for i in 2:(wing.n_unrefined_sections-1) + wing.delta_dist[i] = (wing.delta_dist[i-1] + wing.delta_dist[i] + wing.delta_dist[i+1]) / 3.0 end end end @@ -436,20 +415,20 @@ end """ deform!(wing::Wing, theta_dist::AbstractVector, delta_dist::AbstractVector) -Deform wing by applying theta and delta distributions directly. +Deform wing by applying theta and delta distributions directly to unrefined sections. # Arguments - `wing::Wing`: Wing to deform (must support deformation) -- `theta_dist::AbstractVector`: Twist angle in radians for each panel -- `delta_dist::AbstractVector`: Trailing edge deflection for each panel +- `theta_dist::AbstractVector`: Twist angle in radians for each unrefined section (length = n_unrefined_sections) +- `delta_dist::AbstractVector`: Trailing edge deflection for each unrefined section (length = n_unrefined_sections) # Effects Updates wing.sections with deformed geometry based on wing.non_deformed_sections """ function deform!(wing::Wing, theta_dist::AbstractVector, delta_dist::AbstractVector) !isempty(wing.non_deformed_sections) || throw(ArgumentError("Wing does not support deformation")) - !(length(theta_dist) == wing.n_panels) && throw(ArgumentError("theta_dist and panels are of different lengths")) - !(length(delta_dist) == wing.n_panels) && throw(ArgumentError("delta_dist and panels are of different lengths")) + !(length(theta_dist) == wing.n_unrefined_sections) && throw(ArgumentError("theta_dist must have length $(wing.n_unrefined_sections), got $(length(theta_dist))")) + !(length(delta_dist) == wing.n_unrefined_sections) && throw(ArgumentError("delta_dist must have length $(wing.n_unrefined_sections), got $(length(delta_dist))")) wing.theta_dist .= theta_dist wing.delta_dist .= delta_dist @@ -461,11 +440,16 @@ end Apply stored theta_dist and delta_dist to deform the wing geometry. +Deformation works by: +1. Applying theta/delta angles to unrefined sections (wing.sections) +2. Using refined_panel_mapping to determine which unrefined section each refined section came from +3. Applying the corresponding angle to each refined section + # Arguments - `wing::Wing`: Wing to deform (must have non_deformed_sections) # Effects -Updates wing.sections based on wing.non_deformed_sections and stored distributions +Updates wing.refined_sections based on wing.non_deformed_sections and stored distributions """ function deform!(wing::Wing) !isempty(wing.non_deformed_sections) || return nothing @@ -474,23 +458,25 @@ function deform!(wing::Wing) chord = zeros(MVec3) normal = zeros(MVec3) - # Process all sections (n_panels + 1) - # Each section gets angle(s) from adjacent panel(s) + # Process all refined sections (n_panels + 1) + # Each refined section gets the angle from its corresponding unrefined section for i in 1:(wing.n_panels + 1) - section = wing.non_deformed_sections[i] - - # Determine the angle for this section + # Determine which unrefined section this refined section belongs to if i == 1 - # First section: use angle from first panel - theta = wing.theta_dist[1] + # First section: use first unrefined section + unrefined_idx = 1 elseif i == wing.n_panels + 1 - # Last section: use angle from last panel - theta = wing.theta_dist[wing.n_panels] + # Last section: use last unrefined section + unrefined_idx = wing.n_unrefined_sections else - # Middle sections: average of adjacent panels - theta = 0.5 * (wing.theta_dist[i-1] + wing.theta_dist[i]) + # Middle sections: use the mapping from the panel to the left + unrefined_idx = wing.refined_panel_mapping[i-1] end + theta = wing.theta_dist[unrefined_idx] + + section = wing.non_deformed_sections[i] + # Compute local coordinate system if i < wing.n_panels + 1 section2 = wing.non_deformed_sections[i+1] @@ -696,6 +682,16 @@ function refine_aerodynamic_mesh!(wing::AbstractWing; recompute_mapping=true, so # Update n_unrefined_sections based on actual sections wing.n_unrefined_sections = Int16(length(wing.sections)) + # Resize theta_dist and delta_dist to match n_unrefined_sections + if length(wing.theta_dist) != wing.n_unrefined_sections + resize!(wing.theta_dist, wing.n_unrefined_sections) + fill!(wing.theta_dist, 0.0) + end + if length(wing.delta_dist) != wing.n_unrefined_sections + resize!(wing.delta_dist, wing.n_unrefined_sections) + fill!(wing.delta_dist, 0.0) + end + # Create/update non_deformed_sections to match refined_sections update_non_deformed_sections!(wing) From e500260ef0a15ed3eb61d1aedfe64420f33dcc79 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sat, 6 Dec 2025 10:14:16 +0100 Subject: [PATCH 29/86] Working ram example --- src/VortexStepMethod.jl | 6 ++- src/body_aerodynamics.jl | 6 ++- src/obj_geometry.jl | 24 ++++++--- src/solver.jl | 110 +++++++++++++++++++++++---------------- src/wing_geometry.jl | 17 ++++-- 5 files changed, 104 insertions(+), 59 deletions(-) diff --git a/src/VortexStepMethod.jl b/src/VortexStepMethod.jl index fa2b9c70..937dba01 100644 --- a/src/VortexStepMethod.jl +++ b/src/VortexStepMethod.jl @@ -129,14 +129,16 @@ Enumeration of the implemented panel distributions. - COSINE # Cosine distribution - `COSINE_VAN_GARREL` # van Garrel cosine distribution - `SPLIT_PROVIDED` # Split provided sections -- UNCHANGED # Keep original sections +- `UNCHANGED` # Keep original sections without interpolation +- `NONE` # No refinement - sections already refined """ @enum PanelDistribution begin LINEAR # Linear distribution COSINE # Cosine distribution COSINE_VAN_GARREL # van Garrel cosine distribution SPLIT_PROVIDED # Split provided sections - UNCHANGED # Keep original sections + UNCHANGED # Keep original sections without interpolation + NONE # No refinement - sections already refined end """ diff --git a/src/body_aerodynamics.jl b/src/body_aerodynamics.jl index e4337c28..831242a1 100644 --- a/src/body_aerodynamics.jl +++ b/src/body_aerodynamics.jl @@ -81,7 +81,11 @@ function BodyAerodynamics( section.LE_point .-= kite_body_origin section.TE_point .-= kite_body_origin end - if wing.spanwise_distribution == UNCHANGED + if wing.spanwise_distribution == NONE + # NONE distribution: refined_sections already populated in constructor + !(wing.n_panels == length(wing.refined_sections) - 1) && + throw(ArgumentError("(wing.n_panels = $(wing.n_panels)) != (length(wing.refined_sections) - 1 = $(length(wing.sections) - 1))")) + elseif wing.spanwise_distribution == UNCHANGED wing.refined_sections = wing.sections !(wing.n_panels == length(wing.sections) - 1) && throw(ArgumentError("(wing.n_panels = $(wing.n_panels)) != (length(wing.sections) - 1 = $(length(wing.sections) - 1))")) diff --git a/src/obj_geometry.jl b/src/obj_geometry.jl index e074a402..2a654893 100644 --- a/src/obj_geometry.jl +++ b/src/obj_geometry.jl @@ -381,7 +381,7 @@ This constructor builds a complete aerodynamic model by: 3. Computing inertial properties and coordinate transformations 4. Setting up control surfaces and panel distribution -The resulting Wing supports deformation through group_deform! and deform! functions. +The resulting Wing supports deformation through unrefined_deform! and deform! functions. # Arguments - `obj_path`: Path to .obj file containing 3D wing geometry @@ -395,7 +395,7 @@ The resulting Wing supports deformation through group_deform! and deform! functi - `n_groups=4`: Number of control groups for deformation - `n_sections=n_panels+1`: Number of spanwise cross-sections - `align_to_principal=false`: Align body frame to principal axes of inertia -- `spanwise_distribution=UNCHANGED`: Panel distribution type +- `spanwise_distribution=UNCHANGED`: Panel distribution type (forced to UNCHANGED for ObjWing) - `remove_nan=true`: Interpolate NaN values in aerodynamic data - `alpha_range=deg2rad.(-5:1:20)`: Angle of attack range for polars (rad) - `delta_range=deg2rad.(-5:1:20)`: Trailing edge deflection range for polars (rad) @@ -416,14 +416,14 @@ wing = ObjWing( ) # Apply deformation -group_deform!(wing, deg2rad.([5, 10, 5, 0]), deg2rad.([-5, 0, -5, 0])) +unrefined_deform!(wing, deg2rad.([5, 10, 5, 0]), deg2rad.([-5, 0, -5, 0])) ``` """ function ObjWing( obj_path, dat_path; crease_frac=0.9, wind_vel=10., mass=1.0, n_panels=56, n_sections=nothing, n_unrefined_sections=nothing, n_groups=nothing, - spanwise_distribution=LINEAR, + spanwise_distribution=UNCHANGED, spanwise_direction=[0.0, 1.0, 0.0], remove_nan=true, align_to_principal=false, alpha_range=deg2rad.(-5:1:20), delta_range=deg2rad.(-5:1:20), prn=true, interp_steps=n_panels+1, grouping_method::PanelGroupingMethod=EQUAL_SIZE @@ -445,6 +445,12 @@ function ObjWing( @warn "Parameter grouping_method is deprecated and ignored. Grouping is now always by unrefined sections." maxlog=1 end + # Force NONE distribution for ObjWing + if spanwise_distribution != NONE + @warn "ObjWing only supports spanwise_distribution=NONE. Overriding to NONE." maxlog=1 + spanwise_distribution = NONE + end + # Set default: evenly spaced unrefined sections including both tips if isnothing(n_unrefined_sections) # Default to having same number of unrefined sections as refined (no refinement) @@ -504,8 +510,12 @@ function ObjWing( push!(sections, Section(LE_point, TE_point, POLAR_MATRICES, aero_data)) end - # Initialize refined_sections (will be populated by reinit!) - refined_sections = [Section() for _ in 1:(n_panels+1)] + refined_sections = Section[] + for gamma in range(-gamma_tip, gamma_tip, n_panels+1) + LE_point = [le_interp[i](gamma) for i in 1:3] + TE_point = [te_interp[i](gamma) for i in 1:3] + push!(refined_sections, Section(LE_point, TE_point, POLAR_MATRICES, aero_data)) + end panel_props = PanelProperties{n_panels}() cache = [PreallocationTools.LazyBufferCache()] @@ -513,7 +523,7 @@ function ObjWing( wing = Wing(n_panels, Int16(n_unrefined_sections), spanwise_distribution, panel_props, MVec3(spanwise_direction), sections, refined_sections, remove_nan, Int16[], - Section[], zeros(n_panels), zeros(n_panels), + Section[], zeros(n_unrefined_sections), zeros(n_unrefined_sections), mass, gamma_tip, inertia_tensor, T_cad_body, R_cad_body, radius, le_interp, te_interp, area_interp, cache) diff --git a/src/solver.jl b/src/solver.jl index a7137bfa..7f25f354 100644 --- a/src/solver.jl +++ b/src/solver.jl @@ -22,15 +22,15 @@ Struct for storing the solution of the [solve!](@ref) function. Must contain all - `moment_coeffs`::MVec3: Aerodynamic moment coefficients [CMx, CMy, CMz] [-] - `moment_dist`::Vector{Float64}: Pitching moments around the spanwise vector of each panel. [Nm] - `moment_coeff_dist`::Vector{Float64}: Pitching moment coefficient around the spanwise vector of each panel. [-] -- `unrefined_moment_dist`::MVector{G, Float64}: Aggregated moments for unrefined sections [Nm] -- `unrefined_moment_coeff_dist`::MVector{G, Float64}: Aggregated moment coefficients for unrefined sections [-] -- `cl_unrefined_array`::MVector{G, Float64}: Averaged lift coefficients for unrefined sections [-] -- `cd_unrefined_array`::MVector{G, Float64}: Averaged drag coefficients for unrefined sections [-] -- `cm_unrefined_array`::MVector{G, Float64}: Averaged moment coefficients for unrefined sections [-] -- `alpha_unrefined_array`::MVector{G, Float64}: Averaged angles of attack for unrefined sections [rad] +- `unrefined_moment_dist`::MVector{U, Float64}: Aggregated moments for unrefined sections [Nm] +- `unrefined_moment_coeff_dist`::MVector{U, Float64}: Aggregated moment coefficients for unrefined sections [-] +- `cl_unrefined_array`::MVector{U, Float64}: Averaged lift coefficients for unrefined sections [-] +- `cd_unrefined_array`::MVector{U, Float64}: Averaged drag coefficients for unrefined sections [-] +- `cm_unrefined_array`::MVector{U, Float64}: Averaged moment coefficients for unrefined sections [-] +- `alpha_unrefined_array`::MVector{U, Float64}: Averaged angles of attack for unrefined sections [rad] - `solver_status`::SolverStatus: enum, see [SolverStatus](@ref) """ -@with_kw mutable struct VSMSolution{P,G} +@with_kw mutable struct VSMSolution{P,U} ### private vectors of solve_base! _x_airf_array::Matrix{Float64} = zeros(P, 3) _y_airf_array::Matrix{Float64} = zeros(P, 3) @@ -55,12 +55,12 @@ Struct for storing the solution of the [solve!](@ref) function. Must contain all moment_coeffs::MVec3 = zeros(MVec3) moment_dist::MVector{P, Float64} = zeros(P) moment_coeff_dist::MVector{P, Float64} = zeros(P) - unrefined_moment_dist::MVector{G, Float64} = zeros(G) - unrefined_moment_coeff_dist::MVector{G, Float64} = zeros(G) - cl_unrefined_array::MVector{G, Float64} = zeros(G) - cd_unrefined_array::MVector{G, Float64} = zeros(G) - cm_unrefined_array::MVector{G, Float64} = zeros(G) - alpha_unrefined_array::MVector{G, Float64} = zeros(G) + unrefined_moment_dist::MVector{U, Float64} = zeros(U) + unrefined_moment_coeff_dist::MVector{U, Float64} = zeros(U) + cl_unrefined_array::MVector{U, Float64} = zeros(U) + cd_unrefined_array::MVector{U, Float64} = zeros(U) + cm_unrefined_array::MVector{U, Float64} = zeros(U) + alpha_unrefined_array::MVector{U, Float64} = zeros(U) solver_status::SolverStatus = FAILURE end @@ -105,7 +105,7 @@ Main solver structure for the Vortex Step Method.See also: [solve](@ref) ## Solution sol::VSMSolution = VSMSolution(): The result of calling [solve!](@ref) """ -@with_kw mutable struct Solver{P,G} +@with_kw mutable struct Solver{P,U} # General settings solver_type::SolverType = LOOP aerodynamic_model_type::Model = VSM @@ -139,13 +139,13 @@ sol::VSMSolution = VSMSolution(): The result of calling [solve!](@ref) cache_lin::Vector{PreallocationTools.LazyBufferCache{typeof(identity), typeof(identity)}} = [LazyBufferCache() for _ in 1:4] # Solution - sol::VSMSolution{P,G} = VSMSolution{P,G}() + sol::VSMSolution{P,U} = VSMSolution{P,U}() end function Solver(body_aero; kwargs...) P = length(body_aero.panels) - G = sum([max(0, wing.n_unrefined_sections - 1) for wing in body_aero.wings]) - return Solver{P,G}(; kwargs...) + U = sum([wing.n_unrefined_sections for wing in body_aero.wings]) + return Solver{P,U}(; kwargs...) end function Solver(body_aero, settings::VSMSettings) @@ -719,47 +719,65 @@ function smooth_circulation!( end """ - linearize(solver::Solver, body_aero::BodyAerodynamics, wing::Wing, y::Vector{T}; - theta_idxs=1:4, delta_idxs=nothing, va_idxs=nothing, omega_idxs=nothing, kwargs...) where T + linearize(solver::Solver, body_aero::BodyAerodynamics, y::Vector{T}; + theta_idxs=1:4, delta_idxs=nothing, va_idxs=nothing, omega_idxs=nothing, + aero_coeffs=false, kwargs...) where T -Compute the Jacobian matrix for a deformable wing around an operating point using finite differences. +Compute Jacobian matrix of aerodynamic outputs with respect to control and kinematic inputs using +finite differences. Used for control system design and linear stability analysis. + +The function uses automatic differentiation with finite differences to compute ∂outputs/∂inputs. +Deformations are applied to the wing's unrefined sections (the original sections before mesh +refinement), with each control angle affecting one unrefined section. # Arguments -- `solver`: VSM solver instance (must be initialized) -- `body_aero`: Aerodynamic body representation -- `wing`: Wing model to linearize (must support deformation, i.e., created with ObjWing()) -- `y`: Input vector at operating point, containing a combination of control angles and velocities +- `solver::Solver`: Solver instance (must be configured for the wing) +- `body_aero::BodyAerodynamics`: Body aerodynamics with exactly one wing +- `y::Vector{T}`: Input vector at operating point containing control angles and/or kinematic states # Keyword Arguments -- `theta_idxs`: Indices of twist angles in input vector (default: 1:4) -- `delta_idxs`: Indices of trailing edge deflection angles (default: nothing) -- `va_idxs`: Indices of velocity components `[vx, vy, vz]` (default: nothing) -- `omega_idxs`: Indices of angular velocity components `[ωx, ωy, ωz]` (default: nothing) -- `kwargs...`: Additional arguments passed to the `solve!` function +- `theta_idxs`: Indices in `y` for twist angles (one per unrefined section, default: 1:4) +- `delta_idxs`: Indices in `y` for trailing edge deflections (one per unrefined section, default: nothing) +- `va_idxs`: Indices in `y` for apparent wind velocity [vx, vy, vz] (default: nothing) +- `omega_idxs`: Indices in `y` for angular velocity [ωx, ωy, ωz] (default: nothing) +- `aero_coeffs::Bool`: Return force/moment coefficients instead of dimensional values (default: false) +- `kwargs...`: Additional arguments passed to `solve!` + +# Index Validation +The lengths of `theta_idxs` and `delta_idxs` (if provided) must match `wing.n_unrefined_sections`. +Unrefined sections are the original wing sections before mesh refinement for aerodynamic analysis. + +# Caching +The function caches previous deformation angles to avoid redundant `unrefined_deform!` calls during +Jacobian computation. When the same angles are encountered, geometry deformation is skipped. # Returns -- `jac`: Jacobian matrix (∂outputs/∂inputs) -- `results`: Output vector at the operating point [Fx, Fy, Fz, Mx, My, Mz, unrefined_moments...] +- `jac::Matrix{Float64}`: Jacobian matrix (m×n) where m = 6 + n_unrefined_sections, n = length(y) +- `results::Vector{Float64}`: Output vector at operating point + - If `aero_coeffs=false`: [Fx, Fy, Fz, Mx, My, Mz, unrefined_moment_dist...] + - If `aero_coeffs=true`: [CFx, CFy, CFz, CMx, CMy, CMz, unrefined_moment_coeff_dist...] # Example ```julia -# Initialize wing and solver -wing = ObjWing("path/to/body.obj", "path/to/foil.dat") -body_aero = BodyAerodynamics([wing]) +# Create deformable wing with 4 unrefined sections +wing = ObjWing("kite.obj", "airfoil.dat"; n_unrefined_sections=4) +body_aero = BodyAerodynamics([wing], va=[15.0, 0, 0]) solver = Solver(body_aero) -# Define operating point with 4 control angles, velocity, and angular rates -y_op = [zeros(4); # 4 twist control angles (rad) - [15.0, 0.0, 0.0]; # Velocity vector (m/s) - zeros(3)] # Angular velocity (rad/s) +# Operating point: 4 twist angles + velocity + angular rates +y_op = [zeros(4); # theta angles [rad] + [15.0, 0.0, 0.0]; # va [m/s] + zeros(3)] # omega [rad/s] # Compute Jacobian -jac, results = linearize( - solver, body_aero, wing, y_op; - theta_idxs=1:4, # Twist angles - va_idxs=5:7, # Velocity components - omega_idxs=8:10 # Angular rates +jac, results = linearize(solver, body_aero, y_op; + theta_idxs=1:4, + va_idxs=5:7, + omega_idxs=8:10, + aero_coeffs=true ) + +# jac is (10×10): [6 force/moment coeffs + 4 unrefined moment coeffs] × [4 theta + 3 va + 3 omega] ``` """ function linearize(solver::Solver, body_aero::BodyAerodynamics, y::Vector{T}; @@ -804,20 +822,20 @@ function linearize(solver::Solver, body_aero::BodyAerodynamics, y::Vector{T}; if !isnothing(theta_angles) && isnothing(delta_angles) if !all(theta_angles .== last_theta) - VortexStepMethod.group_deform!(wing, theta_angles, nothing; smooth=false) + VortexStepMethod.unrefined_deform!(wing, theta_angles, nothing; smooth=false) VortexStepMethod.reinit!(body_aero; init_aero=false) last_theta .= theta_angles end elseif !isnothing(theta_angles) && !isnothing(delta_angles) if !all(delta_angles .== last_delta) || !all(theta_angles .== last_theta) - VortexStepMethod.group_deform!(wing, theta_angles, delta_angles; smooth=false) + VortexStepMethod.unrefined_deform!(wing, theta_angles, delta_angles; smooth=false) VortexStepMethod.reinit!(body_aero; init_aero=false) last_theta .= theta_angles last_delta .= delta_angles end elseif isnothing(theta_angles) && !isnothing(delta_angles) if !all(delta_angles .== last_delta) - VortexStepMethod.group_deform!(wing, nothing, delta_angles; smooth=false) + VortexStepMethod.unrefined_deform!(wing, nothing, delta_angles; smooth=false) VortexStepMethod.reinit!(body_aero; init_aero=false) last_delta .= delta_angles end diff --git a/src/wing_geometry.jl b/src/wing_geometry.jl index 7ac9e93c..eee799ca 100644 --- a/src/wing_geometry.jl +++ b/src/wing_geometry.jl @@ -46,7 +46,7 @@ function reinit!(section::Section, LE_point, TE_point, aero_model=nothing, aero_ if !isnothing(aero_data) # NTuple is immutable, so we must assign directly # For mutable types (Vector, Matrix), we can broadcast for efficiency - if aero_data isa NTuple || isnothing(section.aero_data) + if aero_data isa NTuple || aero_data isa Tuple || isnothing(section.aero_data) section.aero_data = aero_data else section.aero_data .= aero_data @@ -344,7 +344,7 @@ function reinit!(wing::AbstractWing; refine_mesh=true, recompute_mapping=true, s end """ - group_deform!(wing::Wing, theta_angles=nothing, delta_angles=nothing; smooth=false) + unrefined_deform!(wing::Wing, theta_angles=nothing, delta_angles=nothing; smooth=false) Apply deformation angles directly to unrefined wing sections. @@ -372,7 +372,7 @@ if both angle inputs are nothing. # Returns - `nothing` (modifies wing in-place) """ -function group_deform!(wing::Wing, theta_angles=nothing, delta_angles=nothing; smooth=false) +function unrefined_deform!(wing::Wing, theta_angles=nothing, delta_angles=nothing; smooth=false) # Check if deformation is supported can_deform = !isempty(wing.non_deformed_sections) @@ -608,6 +608,17 @@ function refine_aerodynamic_mesh!(wing::AbstractWing; recompute_mapping=true, so # Only sort sections if requested (skip for REFINE wings with fixed structural order) sort_sections && sort!(wing.sections, by=s -> s.LE_point[2], rev=true) n_sections = wing.n_panels + 1 + + # Handle NONE distribution - sections already refined, just compute mapping + if wing.spanwise_distribution == NONE + if length(wing.refined_sections) != n_sections + throw(ArgumentError("NONE distribution requires refined_sections to be pre-populated")) + end + recompute_mapping && compute_refined_panel_mapping!(wing) + update_non_deformed_sections!(wing) + return nothing + end + if length(wing.refined_sections) == 0 if wing.spanwise_distribution == UNCHANGED || length(wing.sections) == n_sections wing.refined_sections = wing.sections From a76454c3c66e6918d9bef846238764eeb4e06d80 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sat, 6 Dec 2025 10:49:19 +0100 Subject: [PATCH 30/86] Add combined plot --- examples/Project.toml | 3 + examples/ram_air_kite.jl | 70 +++------- ext/VortexStepMethodMakieExt.jl | 237 +++++++++++++++++++++++++++++++- 3 files changed, 261 insertions(+), 49 deletions(-) diff --git a/examples/Project.toml b/examples/Project.toml index fea9b2fd..f6082789 100644 --- a/examples/Project.toml +++ b/examples/Project.toml @@ -6,3 +6,6 @@ GLMakie = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" VortexStepMethod = "ed3cd733-9f0f-46a9-93e0-89b8d4998dd9" + +[sources] +VortexStepMethod = {path = ".."} diff --git a/examples/ram_air_kite.jl b/examples/ram_air_kite.jl index f47e5938..600acb7a 100644 --- a/examples/ram_air_kite.jl +++ b/examples/ram_air_kite.jl @@ -5,8 +5,8 @@ using LinearAlgebra PLOT = true PRN = true USE_TEX = false -DEFORM = false -LINEARIZE = false +DEFORM = true +LINEARIZE = true # Create wing geometry wing = ObjWing( @@ -22,7 +22,7 @@ println("First init") if DEFORM # Linear interpolation of alpha from 10° at one tip to 0° at the other println("Deform") - @time group_deform!(wing, deg2rad.([10,20,10,0]), deg2rad.([-10,0,-10,0]); smooth=true) + @time VortexStepMethod.unrefined_deform!(wing, deg2rad.([10,20,10,0]), deg2rad.([-10,0,-10,0]); smooth=true) println("Deform init") @time VortexStepMethod.reinit!(body_aero; init_aero=false) end @@ -68,55 +68,29 @@ if LINEARIZE moment_frac=0.1) end -# Plotting polar data -PLOT && plot_polar_data(body_aero) - -# Plotting geometry -PLOT && plot_geometry( - body_aero, - ""; - data_type=".svg", - save_path="", - is_save=false, - is_show=true, - view_elevation=15, - view_azimuth=-120, - use_tex=USE_TEX -) - -# Solving and plotting distributions +# Solving println("Solve") results = VortexStepMethod.solve(solver, body_aero; log=true) @time results = solve(solver, body_aero; log=true) body_y_coordinates = [panel.aero_center[2] for panel in body_aero.panels] -PLOT && plot_distribution( - [body_y_coordinates], - [results], - ["VSM"]; - title="CAD_spanwise_distributions_alpha_$(round(aoa, digits=1))_delta_$(round(side_slip, digits=1))_yaw_$(round(yaw_rate, digits=1))_v_a_$(round(v_a, digits=1))", - data_type=".pdf", - is_save=false, - is_show=true, - use_tex=USE_TEX -) - -PLOT && plot_polars( - [solver], - [body_aero], - [ - "VSM from Ram Air Kite OBJ and DAT file", - ]; - angle_range=range(0, 20, length=20), - angle_type="angle_of_attack", - angle_of_attack=0, - side_slip=0, - v_a=10, - title="ram_kite_panels_$(wing.n_panels)_distribution_$(wing.spanwise_distribution)", - data_type=".pdf", - is_save=false, - is_show=true, - use_tex=USE_TEX -) +if PLOT + plot_combined_analysis( + solver, + body_aero, + results; + solver_label="VSM", + angle_range=range(0, 20, length=20), + angle_type="angle_of_attack", + angle_of_attack=aoa, + side_slip=side_slip, + v_a=v_a, + title="Ram Air Kite (α=$(aoa)°, β=$(side_slip)°, v=$(v_a) m/s)", + view_elevation=15, + view_azimuth=-120, + is_show=true, + use_tex=USE_TEX + ) +end nothing diff --git a/ext/VortexStepMethodMakieExt.jl b/ext/VortexStepMethodMakieExt.jl index 918402a9..1f93c4f7 100644 --- a/ext/VortexStepMethodMakieExt.jl +++ b/ext/VortexStepMethodMakieExt.jl @@ -2,7 +2,8 @@ module VortexStepMethodMakieExt using Makie, VortexStepMethod, LinearAlgebra, Statistics, DelimitedFiles import VortexStepMethod: calculate_filaments_for_plotting -export plot_geometry, plot_distribution, plot_polars, save_plot, show_plot, plot_polar_data +export plot_geometry, plot_distribution, plot_polars, save_plot, show_plot, + plot_polar_data, plot_combined_analysis # Global storage for panel mesh observables (for dynamic plotting) const PANEL_MESH_OBSERVABLES = Ref{Union{Nothing, Dict}}(nothing) @@ -920,4 +921,238 @@ function VortexStepMethod.plot_polar_data(body_aero::BodyAerodynamics; end end +""" + plot_combined_analysis(solver, body_aero, results; + solver_label="VSM", + angle_range=range(0,20,length=20), + angle_type="angle_of_attack", + angle_of_attack=0.0, side_slip=0.0, v_a=10.0, + title="Combined Analysis", + view_elevation=15, view_azimuth=-120, + is_show=true, use_tex=false) + +Create combined multi-panel figure with geometry, polar data, distributions, and polars. + +# Arguments +- `solver`: Aerodynamic solver +- `body_aero`: BodyAerodynamics object +- `results`: Solution dictionary from solve() + +# Keyword arguments +- `solver_label`: Label for solver (default: "VSM") +- `angle_range`: Range of angles for polars (default: range(0,20,length=20)) +- `angle_type`: "angle_of_attack" or "side_slip" (default: "angle_of_attack") +- `angle_of_attack`: AoA in degrees (default: 0.0) +- `side_slip`: Side slip in degrees (default: 0.0) +- `v_a`: Wind speed in m/s (default: 10.0) +- `title`: Overall figure title (default: "Combined Analysis") +- `view_elevation`: Geometry view elevation [°] (default: 15) +- `view_azimuth`: Geometry view azimuth [°] (default: -120) +- `is_show`: Display figure (default: true) +- `use_tex`: Ignored for Makie (default: false) +""" +function VortexStepMethod.plot_combined_analysis( + solver, + body_aero::BodyAerodynamics, + results::Dict; + solver_label="VSM", + angle_range=range(0, 20, length=20), + angle_type="angle_of_attack", + angle_of_attack=0.0, + side_slip=0.0, + v_a=10.0, + title="Combined Analysis", + view_elevation=15, + view_azimuth=-120, + is_show=true, + use_tex=false +) + # Auto-detect screen size and use 80% of it + fig = try + screen_size = Makie.primary_resolution() + fig_width = round(Int, screen_size[1] * 0.8) + fig_height = round(Int, screen_size[2] * 0.8) + Figure(size=(fig_width, fig_height)) + catch + # Fallback if screen detection fails + Figure(size=(1800, 1200)) + end + Label(fig[0, :], title, fontsize=20, font=:bold) + + panels = body_aero.panels + va = isa(body_aero.va, Tuple) ? body_aero.va[1] : body_aero.va + + # [1,1] Wing Geometry + ax_geo = Axis3(fig[1, 1]; + title="Wing Geometry", + xlabel="x", ylabel="y", zlabel="z", + aspect=:data, + azimuth=deg2rad(view_azimuth), + elevation=deg2rad(view_elevation)) + + legend_used = Dict{String,Bool}() + for (i, panel) in enumerate(panels) + corners = [Point3f(panel.corner_points[:, j]) for j in 1:4] + push!(corners, corners[1]) + lines!(ax_geo, corners; color=:grey, linewidth=1, + label = i == 1 ? "Panel Edges" : nothing) + + scatter!(ax_geo, [Point3f(panel.control_point)]; + color=:green, markersize=10, + label = i == 1 ? "Control Points" : nothing) + + scatter!(ax_geo, [Point3f(panel.aero_center)]; + color=:blue, markersize=10, + label = i == 1 ? "Aerodynamic Centers" : nothing) + + filaments = calculate_filaments_for_plotting(panel) + legends = ["Bound Vortex", "side1", "side2", "wake_1", "wake_2"] + + for (filament, legend) in zip(filaments, legends) + x1, x2, color = filament + show_legend = !get(legend_used, legend, false) + plot_line_segment_makie!(ax_geo, [x1, x2], color, + show_legend ? legend : nothing) + legend_used[legend] = true + end + end + + max_chord = maximum(panel.chord for panel in panels) + va_mag = norm(va) + va_vector_begin = -2 * max_chord * va / va_mag + va_vector_end = va_vector_begin + 1.5 * va / va_mag + plot_line_segment_makie!(ax_geo, [va_vector_begin, va_vector_end], + :lightblue, "va") + + set_axes_equal_makie!(ax_geo, panels; zoom=0.5) + axislegend(ax_geo; position=:lt) + + # [1,2] Polar Data Surfaces + if body_aero.panels[1].aero_model == POLAR_MATRICES + alphas = collect(deg2rad.(-5:0.3:25)) + delta_tes = collect(deg2rad.(-5:0.3:25)) + + interp_data = [ + (body_aero.panels[1].cl_interp, "Cl"), + (body_aero.panels[1].cd_interp, "Cd"), + (body_aero.panels[1].cm_interp, "Cm") + ] + + for (idx, (interp, label)) in enumerate(interp_data) + ax = Axis3(fig[1, 2][1, idx]; + title="$label vs α and δ", + xlabel="δ [rad]", + ylabel="α [rad]", + zlabel=label, + azimuth=1.275*π) + + interp_matrix = [interp(alpha, delta_te) + for alpha in alphas, delta_te in delta_tes] + + wireframe!(ax, delta_tes, alphas, interp_matrix; + color=:blue, linewidth=0.5, transparency=true) + end + end + + # [2,1] Spanwise Distributions (3×3 grid) + y_coords = [panel.aero_center[2] for panel in body_aero.panels] + + ax_cl = Axis(fig[2, 1][1, 1], title="CL Distribution", + xlabel="Spanwise Position y/b", ylabel="CL") + ax_cd = Axis(fig[2, 1][1, 2], title="CD Distribution", + xlabel="Spanwise Position y/b", ylabel="CD") + ax_gamma = Axis(fig[2, 1][1, 3], title="Γ Distribution", + xlabel="Spanwise Position y/b", ylabel="Γ") + + ax_alpha_geo = Axis(fig[2, 1][2, 1], title="α Geometric", + xlabel="Spanwise Position y/b", ylabel="α (deg)") + ax_alpha_ac = Axis(fig[2, 1][2, 2], title="α at aero center", + xlabel="Spanwise Position y/b", ylabel="α (deg)") + ax_alpha_unc = Axis(fig[2, 1][2, 3], title="α Uncorrected", + xlabel="Spanwise Position y/b", ylabel="α (deg)") + + ax_fx = Axis(fig[2, 1][3, 1], title="Force x", + xlabel="Spanwise Position y/b", ylabel="Fx") + ax_fy = Axis(fig[2, 1][3, 2], title="Force y", + xlabel="Spanwise Position y/b", ylabel="Fy") + ax_fz = Axis(fig[2, 1][3, 3], title="Force z", + xlabel="Spanwise Position y/b", ylabel="Fz") + + cl_val = round(results["cl"], digits=2) + lines!(ax_cl, Vector(y_coords), Vector(results["cl_distribution"]), + label="$solver_label CL: $cl_val") + axislegend(ax_cl, position=:lt) + + cd_val = round(results["cd"], digits=2) + lines!(ax_cd, Vector(y_coords), Vector(results["cd_distribution"]), + label="$solver_label CD: $cd_val") + axislegend(ax_cd, position=:lt) + + lines!(ax_gamma, Vector(y_coords), Vector(results["gamma_distribution"]), + label=solver_label) + axislegend(ax_gamma, position=:lt) + + lines!(ax_alpha_geo, Vector(y_coords), Vector(results["alpha_geometric"]), + label=solver_label) + axislegend(ax_alpha_geo, position=:lt) + + lines!(ax_alpha_ac, Vector(y_coords), Vector(results["alpha_at_ac"]), + label=solver_label) + axislegend(ax_alpha_ac, position=:lt) + + lines!(ax_alpha_unc, Vector(y_coords), + Vector(results["alpha_uncorrected"]), label=solver_label) + axislegend(ax_alpha_unc, position=:lt) + + force_axes = [ax_fx, ax_fy, ax_fz] + components = ["x", "y", "z"] + for (idx, (ax, comp)) in enumerate(zip(force_axes, components)) + forces = results["F_distribution"][idx, :] + total_force = round(results["F$comp"], digits=2) + lines!(ax, Vector(y_coords), Vector(forces), + label="$solver_label ΣF$comp: $total_force N") + axislegend(ax, position=:lt) + end + + # [2,2] Polars (2×2 grid) + polar_data, rey = generate_polar_data_makie( + solver, body_aero, angle_range; + angle_type, angle_of_attack=deg2rad(angle_of_attack), + side_slip=deg2rad(side_slip), v_a + ) + + label_with_re = "$solver_label Re = $(round(Int64, rey*1e-5))e5" + + ax_cl_polar = Axis(fig[2, 2][1, 1], title="CL vs $angle_type [°]", + xlabel="$angle_type [°]", ylabel="CL") + ax_cd_polar = Axis(fig[2, 2][1, 2], title="CD vs $angle_type [°]", + xlabel="$angle_type [°]", ylabel="CD") + ax_cs_polar = Axis(fig[2, 2][2, 1], title="CS vs $angle_type [°]", + xlabel="$angle_type [°]", ylabel="CS") + ax_polar = Axis(fig[2, 2][2, 2], title="CL vs CD", + xlabel="CD", ylabel="CL") + + scatterlines!(ax_cl_polar, polar_data[1], polar_data[2]; + label=label_with_re, marker=:star5, markersize=12) + axislegend(ax_cl_polar, position=:lt) + + scatterlines!(ax_cd_polar, polar_data[1], polar_data[3]; + label=label_with_re, marker=:star5, markersize=12) + axislegend(ax_cd_polar, position=:lt) + + scatterlines!(ax_cs_polar, polar_data[1], polar_data[4]; + label=label_with_re, marker=:star5, markersize=12) + axislegend(ax_cs_polar, position=:lt) + + scatterlines!(ax_polar, polar_data[3], polar_data[2]; + label=label_with_re, marker=:star5, markersize=12) + axislegend(ax_polar, position=:lt) + + if is_show + display(fig) + end + + return fig +end + end From 55d2d0dc8126b3e33ba3005480495e8404064187 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sat, 6 Dec 2025 11:51:15 +0100 Subject: [PATCH 31/86] Dont use old vsm --- test/Project.toml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/Project.toml b/test/Project.toml index 7b362c6d..fca78da6 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -2,9 +2,9 @@ Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" -ControlPlots = "23c2ee80-7a9e-4350-b264-8e670f12517c" DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" +GLMakie = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a" Interpolations = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" @@ -13,16 +13,15 @@ Serialization = "9e88b42a-f829-5b0c-bbe9-9e923198166b" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" -VortexStepMethod = "ed3cd733-9f0f-46a9-93e0-89b8d4998dd9" YAML = "ddb6d928-2868-570f-bddf-ab3f9cf99eb6" [compat] Aqua = "0.8" BenchmarkTools = "1" CSV = "0.10" -ControlPlots = "0.2.5" DataFrames = "1.7" Documenter = "1.8" +GLMakie = "0" Interpolations = "0.15, 0.16" LinearAlgebra = "1" Logging = "1" From 3f0cf3dcd5631bf0b327957948ed86464d3742d0 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sat, 6 Dec 2025 11:51:44 +0100 Subject: [PATCH 32/86] Actually remove super confusing unrefined panels, simplify to use unrefined segments everywhere --- src/VortexStepMethod.jl | 4 +- src/body_aerodynamics.jl | 31 +++---------- src/solver.jl | 93 ++++++++++++++++++++++----------------- src/wing_geometry.jl | 95 ++++++++++++++++++++-------------------- 4 files changed, 111 insertions(+), 112 deletions(-) diff --git a/src/VortexStepMethod.jl b/src/VortexStepMethod.jl index 937dba01..92710573 100644 --- a/src/VortexStepMethod.jl +++ b/src/VortexStepMethod.jl @@ -43,7 +43,8 @@ export SolverStatus, FEASIBLE, INFEASIBLE, FAILURE export SolverType, LOOP, NONLIN export load_polar_data -export plot_geometry, plot_distribution, plot_circulation_distribution, plot_polars, save_plot, show_plot, plot_polar_data +export plot_geometry, plot_distribution, plot_circulation_distribution, plot_polars, + save_plot, show_plot, plot_polar_data, plot_combined_analysis # the following functions are defined in ext/VortexStepMethodExt.jl function plot_geometry end @@ -53,6 +54,7 @@ function plot_polars end function save_plot end function show_plot end function plot_polar_data end +function plot_combined_analysis end """ const MVec3 = MVector{3, Float64} diff --git a/src/body_aerodynamics.jl b/src/body_aerodynamics.jl index 831242a1..6b3ed591 100644 --- a/src/body_aerodynamics.jl +++ b/src/body_aerodynamics.jl @@ -6,7 +6,6 @@ Main structure for calculating aerodynamic properties of bodies. Use the constru # Fields - panels::Vector{Panel}: Vector of refined [Panel](@ref) structs - wings::Vector{Wing}: A vector of wings; a body can have multiple wings -- unrefined::Vector{Panel}: Vector of unrefined panel representatives for aggregated results - `va::MVec3` = zeros(MVec3): A vector of the apparent wind speed, see: [MVec3](@ref) - `omega`::MVec3 = zeros(MVec3): A vector of the turn rates around the kite body axes - `gamma_distribution`=zeros(Float64, P): A vector of the circulation @@ -25,7 +24,6 @@ Main structure for calculating aerodynamic properties of bodies. Use the constru @with_kw mutable struct BodyAerodynamics{P} panels::Vector{Panel} wings::Vector{Wing} - unrefined::Vector{Panel} = Panel[] _va::MVec3 = zeros(MVec3) omega::MVec3 = zeros(MVec3) gamma_distribution::MVector{P, Float64} = zeros(P) @@ -77,18 +75,18 @@ function BodyAerodynamics( panels = Panel[] n_unrefined_total = 0 for wing in wings - for section in wing.sections + for section in wing.unrefined_sections section.LE_point .-= kite_body_origin section.TE_point .-= kite_body_origin end if wing.spanwise_distribution == NONE # NONE distribution: refined_sections already populated in constructor !(wing.n_panels == length(wing.refined_sections) - 1) && - throw(ArgumentError("(wing.n_panels = $(wing.n_panels)) != (length(wing.refined_sections) - 1 = $(length(wing.sections) - 1))")) + throw(ArgumentError("(wing.n_panels = $(wing.n_panels)) != (length(wing.refined_sections) - 1 = $(length(wing.unrefined_sections) - 1))")) elseif wing.spanwise_distribution == UNCHANGED - wing.refined_sections = wing.sections - !(wing.n_panels == length(wing.sections) - 1) && - throw(ArgumentError("(wing.n_panels = $(wing.n_panels)) != (length(wing.sections) - 1 = $(length(wing.sections) - 1))")) + wing.refined_sections = wing.unrefined_sections + !(wing.n_panels == length(wing.unrefined_sections) - 1) && + throw(ArgumentError("(wing.n_panels = $(wing.n_panels)) != (length(wing.unrefined_sections) - 1 = $(length(wing.unrefined_sections) - 1))")) else wing.refined_sections = Section[Section() for _ in 1:wing.n_panels+1] end @@ -98,15 +96,9 @@ function BodyAerodynamics( panel = Panel() push!(panels, panel) end - - # Count total unrefined panels (sections - 1) - n_unrefined_total += max(0, wing.n_unrefined_sections - 1) end - # Initialize unrefined panels (representatives for unrefined sections) - unrefined = [Panel() for _ in 1:max(0, n_unrefined_total)] - - body_aero = BodyAerodynamics{length(panels)}(; panels, wings, unrefined) + body_aero = BodyAerodynamics{length(panels)}(; panels, wings) reinit!(body_aero; va, omega) return body_aero end @@ -191,17 +183,6 @@ function reinit!(body_aero::BodyAerodynamics; end end - # Resize unrefined vector if needed (after wings are reinitialized and n_unrefined_sections is set) - n_unrefined_total = sum([max(0, wing.n_unrefined_sections - 1) for wing in body_aero.wings]) - if length(body_aero.unrefined) != n_unrefined_total - resize!(body_aero.unrefined, n_unrefined_total) - for i in 1:n_unrefined_total - if !isassigned(body_aero.unrefined, i) - body_aero.unrefined[i] = Panel() - end - end - end - # Initialize rest of the struct body_aero.projected_area = sum(calculate_projected_area, body_aero.wings) calculate_stall_angle_list!(body_aero.stall_angle_list, body_aero.panels) diff --git a/src/solver.jl b/src/solver.jl index 7f25f354..111e2cea 100644 --- a/src/solver.jl +++ b/src/solver.jl @@ -61,6 +61,12 @@ Struct for storing the solution of the [solve!](@ref) function. Must contain all cd_unrefined_array::MVector{U, Float64} = zeros(U) cm_unrefined_array::MVector{U, Float64} = zeros(U) alpha_unrefined_array::MVector{U, Float64} = zeros(U) + x_airf_unrefined_array::Vector{MVec3} = [MVec3(0,0,0) for _ in 1:U] + y_airf_unrefined_array::Vector{MVec3} = [MVec3(0,0,0) for _ in 1:U] + z_airf_unrefined_array::Vector{MVec3} = [MVec3(0,0,0) for _ in 1:U] + va_unrefined_array::Vector{MVec3} = [MVec3(0,0,0) for _ in 1:U] + chord_unrefined_array::MVector{U, Float64} = zeros(U) + width_unrefined_array::MVector{U, Float64} = zeros(U) solver_status::SolverStatus = FAILURE end @@ -312,69 +318,78 @@ function solve!(solver::Solver, body_aero::BodyAerodynamics, gamma_distribution= cd_unrefined_array = solver.sol.cd_unrefined_array cm_unrefined_array = solver.sol.cm_unrefined_array alpha_unrefined_array = solver.sol.alpha_unrefined_array + x_airf_unrefined_array = solver.sol.x_airf_unrefined_array + y_airf_unrefined_array = solver.sol.y_airf_unrefined_array + z_airf_unrefined_array = solver.sol.z_airf_unrefined_array + va_unrefined_array = solver.sol.va_unrefined_array + chord_unrefined_array = solver.sol.chord_unrefined_array + width_unrefined_array = solver.sol.width_unrefined_array + + # Zero all unrefined arrays unrefined_moment_dist .= 0.0 unrefined_moment_coeff_dist .= 0.0 cl_unrefined_array .= 0.0 cd_unrefined_array .= 0.0 cm_unrefined_array .= 0.0 alpha_unrefined_array .= 0.0 + for i in eachindex(x_airf_unrefined_array) + x_airf_unrefined_array[i] .= 0.0 + y_airf_unrefined_array[i] .= 0.0 + z_airf_unrefined_array[i] .= 0.0 + va_unrefined_array[i] .= 0.0 + end + chord_unrefined_array .= 0.0 + width_unrefined_array .= 0.0 + panel_idx = 1 unrefined_idx = 1 for wing in body_aero.wings - n_unrefined_panels = wing.n_unrefined_sections - 1 - if n_unrefined_panels > 0 - # Initialize unrefined panels - for i in 1:n_unrefined_panels - target_unrefined_idx = unrefined_idx + i - 1 - unrefined_panel = body_aero.unrefined[target_unrefined_idx] - unrefined_panel.x_airf .= 0.0 - unrefined_panel.y_airf .= 0.0 - unrefined_panel.z_airf .= 0.0 - unrefined_panel.va .= 0.0 - unrefined_panel.chord = 0.0 - unrefined_panel.width = 0.0 - end - # Accumulate values from refined panels - unrefined_panel_counts = zeros(Int, n_unrefined_panels) + if wing.n_unrefined_sections > 0 + # Accumulate values from refined panels to unrefined sections + unrefined_section_counts = zeros(Int, wing.n_unrefined_sections) for local_panel_idx in 1:wing.n_panels panel = body_aero.panels[panel_idx] - original_panel_idx = wing.refined_panel_mapping[local_panel_idx] - target_unrefined_idx = unrefined_idx + original_panel_idx - 1 - unrefined_panel = body_aero.unrefined[target_unrefined_idx] + original_section_idx = wing.refined_panel_mapping[local_panel_idx] + target_unrefined_idx = unrefined_idx + original_section_idx - 1 + + # Accumulate coefficients and moments unrefined_moment_dist[target_unrefined_idx] += moment_dist[panel_idx] unrefined_moment_coeff_dist[target_unrefined_idx] += moment_coeff_dist[panel_idx] cl_unrefined_array[target_unrefined_idx] += solver.sol.cl_array[panel_idx] cd_unrefined_array[target_unrefined_idx] += solver.sol.cd_array[panel_idx] cm_unrefined_array[target_unrefined_idx] += solver.sol.cm_array[panel_idx] alpha_unrefined_array[target_unrefined_idx] += solver.sol.alpha_array[panel_idx] + # Accumulate geometry - unrefined_panel.x_airf .+= panel.x_airf - unrefined_panel.y_airf .+= panel.y_airf - unrefined_panel.z_airf .+= panel.z_airf - unrefined_panel.va .+= panel.va - unrefined_panel.chord += panel.chord - unrefined_panel.width += panel.width - unrefined_panel_counts[original_panel_idx] += 1 + x_airf_unrefined_array[target_unrefined_idx] .+= panel.x_airf + y_airf_unrefined_array[target_unrefined_idx] .+= panel.y_airf + z_airf_unrefined_array[target_unrefined_idx] .+= panel.z_airf + va_unrefined_array[target_unrefined_idx] .+= panel.va + chord_unrefined_array[target_unrefined_idx] += panel.chord + width_unrefined_array[target_unrefined_idx] += panel.width + + unrefined_section_counts[original_section_idx] += 1 panel_idx += 1 end + # Average coefficients and geometry - for i in 1:n_unrefined_panels + for i in 1:wing.n_unrefined_sections target_unrefined_idx = unrefined_idx + i - 1 - if unrefined_panel_counts[i] > 0 - unrefined_panel = body_aero.unrefined[target_unrefined_idx] - cl_unrefined_array[target_unrefined_idx] /= unrefined_panel_counts[i] - cd_unrefined_array[target_unrefined_idx] /= unrefined_panel_counts[i] - cm_unrefined_array[target_unrefined_idx] /= unrefined_panel_counts[i] - alpha_unrefined_array[target_unrefined_idx] /= unrefined_panel_counts[i] - unrefined_panel.x_airf ./= unrefined_panel_counts[i] - unrefined_panel.y_airf ./= unrefined_panel_counts[i] - unrefined_panel.z_airf ./= unrefined_panel_counts[i] - unrefined_panel.va ./= unrefined_panel_counts[i] - unrefined_panel.chord /= unrefined_panel_counts[i] - unrefined_panel.width /= unrefined_panel_counts[i] + if unrefined_section_counts[i] > 0 + count = unrefined_section_counts[i] + cl_unrefined_array[target_unrefined_idx] /= count + cd_unrefined_array[target_unrefined_idx] /= count + cm_unrefined_array[target_unrefined_idx] /= count + alpha_unrefined_array[target_unrefined_idx] /= count + x_airf_unrefined_array[target_unrefined_idx] ./= count + y_airf_unrefined_array[target_unrefined_idx] ./= count + z_airf_unrefined_array[target_unrefined_idx] ./= count + va_unrefined_array[target_unrefined_idx] ./= count + chord_unrefined_array[target_unrefined_idx] /= count + width_unrefined_array[target_unrefined_idx] /= count end end - unrefined_idx += n_unrefined_panels + unrefined_idx += wing.n_unrefined_sections else # Skip panels for wings with no unrefined sections panel_idx += wing.n_panels diff --git a/src/wing_geometry.jl b/src/wing_geometry.jl index eee799ca..857f5fe5 100644 --- a/src/wing_geometry.jl +++ b/src/wing_geometry.jl @@ -227,12 +227,12 @@ mutable struct Wing <: AbstractWing spanwise_distribution::PanelDistribution panel_props::PanelProperties spanwise_direction::MVec3 - sections::Vector{Section} + unrefined_sections::Vector{Section} refined_sections::Vector{Section} remove_nan::Bool # Grouping - refined_panel_mapping::Vector{Int16} # Maps each refined panel to its original unrefined section index + refined_panel_mapping::Vector{Int16} # Maps each refined panel index to unrefined section index (1 to n_unrefined_sections) # Deformation fields non_deformed_sections::Vector{Section} @@ -423,7 +423,7 @@ Deform wing by applying theta and delta distributions directly to unrefined sect - `delta_dist::AbstractVector`: Trailing edge deflection for each unrefined section (length = n_unrefined_sections) # Effects -Updates wing.sections with deformed geometry based on wing.non_deformed_sections +Updates wing.unrefined_sections with deformed geometry based on wing.non_deformed_sections """ function deform!(wing::Wing, theta_dist::AbstractVector, delta_dist::AbstractVector) !isempty(wing.non_deformed_sections) || throw(ArgumentError("Wing does not support deformation")) @@ -441,7 +441,7 @@ end Apply stored theta_dist and delta_dist to deform the wing geometry. Deformation works by: -1. Applying theta/delta angles to unrefined sections (wing.sections) +1. Applying theta/delta angles to unrefined sections (wing.unrefined_sections) 2. Using refined_panel_mapping to determine which unrefined section each refined section came from 3. Applying the corresponding angle to each refined section @@ -545,7 +545,7 @@ function add_section!(wing::Wing, LE_point, elseif aero_model == POLAR_MATRICES && wing.remove_nan interpolate_matrix_nans!.(aero_data[3:5]) end - push!(wing.sections, Section(LE_point, TE_point, aero_model, aero_data)) + push!(wing.unrefined_sections, Section(LE_point, TE_point, aero_model, aero_data)) return nothing end @@ -606,7 +606,7 @@ Returns: """ function refine_aerodynamic_mesh!(wing::AbstractWing; recompute_mapping=true, sort_sections=true) # Only sort sections if requested (skip for REFINE wings with fixed structural order) - sort_sections && sort!(wing.sections, by=s -> s.LE_point[2], rev=true) + sort_sections && sort!(wing.unrefined_sections, by=s -> s.LE_point[2], rev=true) n_sections = wing.n_panels + 1 # Handle NONE distribution - sections already refined, just compute mapping @@ -620,8 +620,8 @@ function refine_aerodynamic_mesh!(wing::AbstractWing; recompute_mapping=true, so end if length(wing.refined_sections) == 0 - if wing.spanwise_distribution == UNCHANGED || length(wing.sections) == n_sections - wing.refined_sections = wing.sections + if wing.spanwise_distribution == UNCHANGED || length(wing.unrefined_sections) == n_sections + wing.refined_sections = wing.unrefined_sections update_non_deformed_sections!(wing) return nothing else @@ -630,13 +630,13 @@ function refine_aerodynamic_mesh!(wing::AbstractWing; recompute_mapping=true, so end # Extract geometry data - n_current = length(wing.sections) + n_current = length(wing.unrefined_sections) LE = zeros(Float64, n_current, 3) TE = zeros(Float64, n_current, 3) - aero_model = Vector{typeof(wing.sections[1].aero_model)}() - aero_data = Vector{typeof(wing.sections[1].aero_data)}() + aero_model = Vector{typeof(wing.unrefined_sections[1].aero_model)}() + aero_data = Vector{typeof(wing.unrefined_sections[1].aero_data)}() - for (i, section) in enumerate(wing.sections) + for (i, section) in enumerate(wing.unrefined_sections) LE[i,:] = section.LE_point TE[i,:] = section.TE_point push!(aero_model, section.aero_model) @@ -649,16 +649,16 @@ function refine_aerodynamic_mesh!(wing::AbstractWing; recompute_mapping=true, so end # Handle special cases - if wing.spanwise_distribution == UNCHANGED || length(wing.sections) == n_sections - for i in eachindex(wing.sections) - reinit!(wing.refined_sections[i], wing.sections[i]) + if wing.spanwise_distribution == UNCHANGED || length(wing.unrefined_sections) == n_sections + for i in eachindex(wing.unrefined_sections) + reinit!(wing.refined_sections[i], wing.unrefined_sections[i]) end recompute_mapping && compute_refined_panel_mapping!(wing) update_non_deformed_sections!(wing) return nothing end - @debug "Refining aerodynamic mesh from $(length(wing.sections)) sections to $n_sections sections." + @debug "Refining aerodynamic mesh from $(length(wing.unrefined_sections)) sections to $n_sections sections." # Handle two-section case if n_sections == 2 @@ -687,11 +687,11 @@ function refine_aerodynamic_mesh!(wing::AbstractWing; recompute_mapping=true, so throw(ArgumentError("Unsupported spanwise panel distribution: $(wing.spanwise_distribution)")) end - # Compute panel mapping by finding closest unrefined panel for each refined panel + # Compute panel mapping by finding closest unrefined section for each refined panel recompute_mapping && compute_refined_panel_mapping!(wing) # Update n_unrefined_sections based on actual sections - wing.n_unrefined_sections = Int16(length(wing.sections)) + wing.n_unrefined_sections = Int16(length(wing.unrefined_sections)) # Resize theta_dist and delta_dist to match n_unrefined_sections if length(wing.theta_dist) != wing.n_unrefined_sections @@ -713,12 +713,14 @@ end """ compute_refined_panel_mapping!(wing::AbstractWing) -Compute the mapping from refined panels to unrefined panels by finding -the closest unrefined panel for each refined panel (based on panel center distance). +Compute the mapping from refined panels to unrefined sections by finding +the closest unrefined section for each refined panel (based on section center distance). +Maps each refined panel index to its corresponding unrefined section index +(1 to n_unrefined_sections). This is non-allocating and works after refinement is complete. """ function compute_refined_panel_mapping!(wing::AbstractWing) - n_unrefined_sections = length(wing.sections) + n_unrefined_sections = length(wing.unrefined_sections) n_refined_panels = wing.n_panels # Handle case where no refinement occurred @@ -732,16 +734,15 @@ function compute_refined_panel_mapping!(wing::AbstractWing) wing.refined_panel_mapping = zeros(Int16, n_refined_panels) end - # Compute centers of unrefined panels - n_unrefined_panels = n_unrefined_sections - 1 - unrefined_centers = Vector{MVec3}(undef, n_unrefined_panels) - for i in 1:n_unrefined_panels - le_mid = (wing.sections[i].LE_point + wing.sections[i+1].LE_point) / 2 - te_mid = (wing.sections[i].TE_point + wing.sections[i+1].TE_point) / 2 - unrefined_centers[i] = MVec3((le_mid + te_mid) / 2) + # Compute centers of unrefined sections + unrefined_centers = Vector{MVec3}(undef, n_unrefined_sections) + for i in 1:n_unrefined_sections + le_point = wing.unrefined_sections[i].LE_point + te_point = wing.unrefined_sections[i].TE_point + unrefined_centers[i] = MVec3((le_point + te_point) / 2) end - # For each refined panel, find closest unrefined panel + # For each refined panel, find closest unrefined section for refined_panel_idx in 1:n_refined_panels le_mid = (wing.refined_sections[refined_panel_idx].LE_point + wing.refined_sections[refined_panel_idx+1].LE_point) / 2 @@ -749,14 +750,14 @@ function compute_refined_panel_mapping!(wing::AbstractWing) wing.refined_sections[refined_panel_idx+1].TE_point) / 2 refined_center = MVec3((le_mid + te_mid) / 2) - # Find closest unrefined panel + # Find closest unrefined section min_dist = Inf closest_idx = 1 - for unrefined_panel_idx in 1:n_unrefined_panels - dist = norm(refined_center - unrefined_centers[unrefined_panel_idx]) + for unrefined_section_idx in 1:n_unrefined_sections + dist = norm(refined_center - unrefined_centers[unrefined_section_idx]) if dist < min_dist min_dist = dist - closest_idx = unrefined_panel_idx + closest_idx = unrefined_section_idx end end @@ -1039,7 +1040,7 @@ Returns: Vector{Section}: Refined sections """ function refine_mesh_by_splitting_provided_sections!(wing::AbstractWing) - n_sections_provided = length(wing.sections) + n_sections_provided = length(wing.unrefined_sections) n_panels_provided = n_sections_provided - 1 n_panels_desired = wing.n_panels @@ -1047,7 +1048,7 @@ function refine_mesh_by_splitting_provided_sections!(wing::AbstractWing) # Check if refinement is needed if n_panels_provided == n_panels_desired - for (refined_section, section) in zip(wing.refined_sections, wing.sections) + for (refined_section, section) in zip(wing.refined_sections, wing.unrefined_sections) reinit!(refined_section, section) end return nothing @@ -1067,16 +1068,16 @@ function refine_mesh_by_splitting_provided_sections!(wing::AbstractWing) new_sections_per_pair, remaining = divrem(n_new_sections, n_section_pairs) # Extract geometry data - LE = [section.LE_point for section in wing.sections] - TE = [section.TE_point for section in wing.sections] - aero_model = [section.aero_model for section in wing.sections] - aero_data = [section.aero_data for section in wing.sections] + LE = [section.LE_point for section in wing.unrefined_sections] + TE = [section.TE_point for section in wing.unrefined_sections] + aero_model = [section.aero_model for section in wing.unrefined_sections] + aero_data = [section.aero_data for section in wing.unrefined_sections] # Process each section pair idx = 1 for left_section_index in 1:n_section_pairs # Add left section of pair - reinit!(wing.refined_sections[idx], wing.sections[left_section_index]) + reinit!(wing.refined_sections[idx], wing.unrefined_sections[left_section_index]) idx += 1 # Calculate new sections for this pair @@ -1111,7 +1112,7 @@ function refine_mesh_by_splitting_provided_sections!(wing::AbstractWing) end # Add final section - reinit!(wing.refined_sections[idx], wing.sections[end]) + reinit!(wing.refined_sections[idx], wing.unrefined_sections[end]) idx += 1 # Validate result @@ -1137,7 +1138,7 @@ function calculate_span(wing::AbstractWing) # Get all points all_points = reduce(vcat, [[section.LE_point, section.TE_point] - for section in wing.sections]) + for section in wing.unrefined_sections]) # Project points and calculate span projections = [dot(point, vector_axis) for point in all_points] @@ -1170,12 +1171,12 @@ function calculate_projected_area(wing::AbstractWing, # Calculate area by summing trapezoid areas projected_area = 0.0 - for i in 1:(length(wing.sections)-1) + for i in 1:(length(wing.unrefined_sections)-1) # Get section points - LE_current = wing.sections[i].LE_point - TE_current = wing.sections[i].TE_point - LE_next = wing.sections[i+1].LE_point - TE_next = wing.sections[i+1].TE_point + LE_current = wing.unrefined_sections[i].LE_point + TE_current = wing.unrefined_sections[i].TE_point + LE_next = wing.unrefined_sections[i+1].LE_point + TE_next = wing.unrefined_sections[i+1].TE_point # Project points project_onto_plane!(LE_current_proj, LE_current, z_plane_vector) From c536ba936b473e429eb2b89c0496fdc1b40fd562 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sat, 6 Dec 2025 11:56:57 +0100 Subject: [PATCH 33/86] Adjust for using the unrefined segment approach --- .../test_body_aerodynamics.jl | 16 +- test/body_aerodynamics/test_results.jl | 22 +-- test/plotting/test_plotting.jl | 20 +-- test/ram_geometry/test_kite_geometry.jl | 28 ++-- test/solver/test_group_coefficients.jl | 148 ------------------ test/test_data_utils.jl | 2 - test/wing_geometry/test_wing_geometry.jl | 42 ++--- test/yaml_geometry/test_wing_constructor.jl | 106 ++++++------- .../test_yaml_wing_deformation.jl | 43 ++--- 9 files changed, 131 insertions(+), 296 deletions(-) delete mode 100644 test/solver/test_group_coefficients.jl diff --git a/test/body_aerodynamics/test_body_aerodynamics.jl b/test/body_aerodynamics/test_body_aerodynamics.jl index c022102f..239e5113 100644 --- a/test/body_aerodynamics/test_body_aerodynamics.jl +++ b/test/body_aerodynamics/test_body_aerodynamics.jl @@ -126,12 +126,12 @@ end body_aero = BodyAerodynamics([wing]; kite_body_origin=origin) # Check if sections are correctly translated - @test wing.sections[3].LE_point ≈ [-1.0, -2.0, -3.0] - @test wing.sections[3].TE_point ≈ [0.0, -2.0, -3.0] - @test wing.sections[2].LE_point ≈ [-1.0, -1.0, -3.0] - @test wing.sections[2].TE_point ≈ [0.0, -1.0, -3.0] - @test wing.sections[1].LE_point ≈ [-1.0, 0.0, -3.0] - @test wing.sections[1].TE_point ≈ [0.0, 0.0, -3.0] + @test wing.unrefined_sections[3].LE_point ≈ [-1.0, -2.0, -3.0] + @test wing.unrefined_sections[3].TE_point ≈ [0.0, -2.0, -3.0] + @test wing.unrefined_sections[2].LE_point ≈ [-1.0, -1.0, -3.0] + @test wing.unrefined_sections[2].TE_point ≈ [0.0, -1.0, -3.0] + @test wing.unrefined_sections[1].LE_point ≈ [-1.0, 0.0, -3.0] + @test wing.unrefined_sections[1].TE_point ≈ [0.0, 0.0, -3.0] end function create_geometry(; model=VSM, wing_type=:rectangular, plotting=false, N=40) @@ -351,8 +351,8 @@ end @test loop_sol.solver_status == FEASIBLE - @test sum(loop_sol.moment_dist) ≈ sum(loop_sol.group_moment_dist) - @test sum(nonlin_sol.moment_dist) ≈ sum(nonlin_sol.group_moment_dist) + @test sum(loop_sol.moment_dist) ≈ sum(loop_sol.unrefined_moment_dist) + @test sum(nonlin_sol.moment_dist) ≈ sum(nonlin_sol.unrefined_moment_dist) end diff --git a/test/body_aerodynamics/test_results.jl b/test/body_aerodynamics/test_results.jl index 60d2d4cf..80be8585 100644 --- a/test/body_aerodynamics/test_results.jl +++ b/test/body_aerodynamics/test_results.jl @@ -31,7 +31,7 @@ if !@isdefined ram_wing_results error("Required data files not found: $body_src or $foil_src") end - ram_wing = ObjWing(body_path, foil_path; alpha_range=deg2rad.(-1:1), delta_range=deg2rad.(-1:1)) + ram_wing = ObjWing(body_path, foil_path; alpha_range=deg2rad.(-1:1), delta_range=deg2rad.(-1:1), n_unrefined_sections=4) end @testset "Nonlinear vs Linear - Comprehensive Input Testing" begin @@ -48,7 +48,7 @@ end domega_magnitudes = [deg2rad(0.1), deg2rad(0.5), deg2rad(1.0)] # Angular rate perturbations (rad/s) # Create body aerodynamics and solver - VortexStepMethod.group_deform!(ram_wing, theta, delta; smooth=false) + VortexStepMethod.unrefined_deform!(ram_wing, theta, delta; smooth=false) body_aero = BodyAerodynamics([ram_wing]; va, omega) solver = Solver(body_aero; aerodynamic_model_type=VSM, @@ -85,8 +85,8 @@ end # Verify that linearization results match nonlinear results at operating point baseline_res = VortexStepMethod.solve!(solver, body_aero; log=false) - baseline_res = [solver.sol.force; solver.sol.moment; solver.sol.group_moment_dist] - coeff_baseline_res = [solver.sol.force_coeffs; solver.sol.moment_coeffs; solver.sol.group_moment_coeff_dist] + baseline_res = [solver.sol.force; solver.sol.moment; solver.sol.unrefined_moment_dist] + coeff_baseline_res = [solver.sol.force_coeffs; solver.sol.moment_coeffs; solver.sol.unrefined_moment_coeff_dist] @test baseline_res ≈ lin_res @test coeff_baseline_res ≈ coeff_lin_res @@ -137,13 +137,13 @@ end else throw(ArgumentError()) end - VortexStepMethod.group_deform!(ram_wing, reset_theta, reset_delta; smooth=false) + VortexStepMethod.unrefined_deform!(ram_wing, reset_theta, reset_delta; smooth=false) reinit!(body_aero; init_aero=false, va=reset_va, omega=reset_omega) # Get nonlinear solution nonlin_res = VortexStepMethod.solve!(solver, body_aero, nothing; log=false) - nonlin_res = [solver.sol.force; solver.sol.moment; solver.sol.group_moment_dist] - coeff_nonlin_res = [solver.sol.force_coeffs; solver.sol.moment_coeffs; solver.sol.group_moment_coeff_dist] + nonlin_res = [solver.sol.force; solver.sol.moment; solver.sol.unrefined_moment_dist] + coeff_nonlin_res = [solver.sol.force_coeffs; solver.sol.moment_coeffs; solver.sol.unrefined_moment_coeff_dist] @test nonlin_res ≉ baseline_res @test coeff_nonlin_res ≉ baseline_res @@ -220,7 +220,7 @@ end for (combo_name, active_indices, perturbation, idx_mappings) in combination_tests @testset "$combo_name" begin # Start with a fresh model for each combination test - VortexStepMethod.group_deform!(ram_wing, theta, delta; smooth=false) + VortexStepMethod.unrefined_deform!(ram_wing, theta, delta; smooth=false) reinit!(body_aero; init_aero=false, va, omega) # Create the appropriate input vector for this combination @@ -250,7 +250,7 @@ end # Get baseline results baseline_res = VortexStepMethod.solve!(solver, body_aero; log=false) - baseline_res = [solver.sol.force; solver.sol.moment; solver.sol.group_moment_dist] + baseline_res = [solver.sol.force; solver.sol.moment; solver.sol.unrefined_moment_dist] # Should match the linearization result @test baseline_res ≈ lin_res_combo @@ -272,12 +272,12 @@ end perturbed_input[idx_mappings.delta_idxs] : delta # Apply to nonlinear model - VortexStepMethod.group_deform!(ram_wing, perturbed_theta, perturbed_delta; smooth=false) + VortexStepMethod.unrefined_deform!(ram_wing, perturbed_theta, perturbed_delta; smooth=false) reinit!(body_aero; init_aero=false, va=perturbed_va, omega=perturbed_omega) # Get nonlinear solution with perturbation nonlin_res = VortexStepMethod.solve!(solver, body_aero; log=false) - nonlin_res = [solver.sol.force; solver.sol.moment; solver.sol.group_moment_dist] + nonlin_res = [solver.sol.force; solver.sol.moment; solver.sol.unrefined_moment_dist] # Compute linearized prediction using our specialized Jacobian lin_prediction = lin_res_combo + jac_combo * perturbation diff --git a/test/plotting/test_plotting.jl b/test/plotting/test_plotting.jl index e1f82959..eba66aa2 100644 --- a/test/plotting/test_plotting.jl +++ b/test/plotting/test_plotting.jl @@ -1,5 +1,5 @@ using VortexStepMethod -using ControlPlots +using GLMakie using Test # Resolve repo data directory for ram air kite assets @@ -63,17 +63,8 @@ function create_body_aero() body_aero end -plt.ioff() @testset "Plotting" begin - fig = plt.figure(figsize=(14, 14)) - res = plt.plot([1,2,3]) - @test fig isa plt.PyPlot.Figure - @test res isa Vector{plt.PyObject} save_dir = tempdir() - save_plot(fig, save_dir, "plot") - @test isfile(joinpath(save_dir, "plot.pdf")) - safe_rm(joinpath(save_dir, "plot.pdf")) - show_plot(fig) body_aero = create_body_aero() if Sys.islinux() fig = plot_geometry( @@ -83,7 +74,7 @@ plt.ioff() save_path=save_dir, is_save=true, is_show=false) - @test fig isa plt.PyPlot.Figure + @test fig isa Figure @test isfile(joinpath(save_dir, "Rectangular_wing_geometry_angled_view.pdf")) safe_rm(joinpath(save_dir, "Rectangular_wing_geometry_angled_view.pdf")) @test isfile(joinpath(save_dir, "Rectangular_wing_geometry_front_view.pdf")) @@ -110,7 +101,7 @@ plt.ioff() ["VSM", "LLT"], title="Spanwise Distributions" ) - @test fig isa plt.PyPlot.Figure + @test fig isa Figure # Step 8: Plot polar curves v_a = 20.0 # Magnitude of inflow velocity [m/s] @@ -128,15 +119,14 @@ plt.ioff() is_save=true, is_show=false ) - @test fig isa plt.PyPlot.Figure + @test fig isa Figure @test isfile(joinpath(save_dir, "Rectangular_Wing_Polars.pdf")) safe_rm(joinpath(save_dir, "Rectangular_Wing_Polars.pdf")) # Step 9: Test polar data plotting body_aero = BodyAerodynamics([ram_wing]) fig = plot_polar_data(body_aero; is_show=false) - @test fig isa plt.PyPlot.Figure + @test fig isa Figure end end -plt.ion() nothing \ No newline at end of file diff --git a/test/ram_geometry/test_kite_geometry.jl b/test/ram_geometry/test_kite_geometry.jl index c4d35500..d76cc533 100644 --- a/test/ram_geometry/test_kite_geometry.jl +++ b/test/ram_geometry/test_kite_geometry.jl @@ -171,18 +171,18 @@ using Serialization @test wing.n_panels == 56 # Default value @test wing.spanwise_distribution == UNCHANGED @test wing.spanwise_direction ≈ [0.0, 1.0, 0.0] - @test length(wing.sections) > 0 # Should have sections now + @test length(wing.unrefined_sections) > 0 # Should have sections now @test wing.mass ≈ 1.0 @test wing.radius ≈ r rtol=1e-2 @test wing.gamma_tip ≈ π/4 rtol=1e-2 - @test !isnan(wing.sections[1].aero_data[3][end]) - @test !isnan(wing.sections[1].aero_data[4][end]) - @test !isnan(wing.sections[1].aero_data[5][end]) + @test !isnan(wing.unrefined_sections[1].aero_data[3][end]) + @test !isnan(wing.unrefined_sections[1].aero_data[4][end]) + @test !isnan(wing.unrefined_sections[1].aero_data[5][end]) wing = ObjWing(test_obj_path, test_dat_path; remove_nan=false) - @test isnan(wing.sections[1].aero_data[3][end]) - @test isnan(wing.sections[1].aero_data[4][end]) - @test isnan(wing.sections[1].aero_data[5][end]) + @test isnan(wing.unrefined_sections[1].aero_data[3][end]) + @test isnan(wing.unrefined_sections[1].aero_data[4][end]) + @test isnan(wing.unrefined_sections[1].aero_data[5][end]) end @testset "Wing Deformation" begin @@ -195,8 +195,8 @@ using Serialization original_te_point = copy(body_aero.panels[i].TE_point_1) # Apply deformation with non-zero angles - theta_dist = fill(deg2rad(30.0), wing.n_panels) # 10 degrees twist - delta_dist = fill(deg2rad(5.0), wing.n_panels) # 5 degrees trailing edge deflection + theta_dist = fill(deg2rad(30.0), wing.n_unrefined_sections) # 30 degrees twist for all sections + delta_dist = fill(deg2rad(5.0), wing.n_unrefined_sections) # 5 degrees trailing edge deflection for all sections VortexStepMethod.deform!(wing, theta_dist, delta_dist) VortexStepMethod.reinit!(body_aero) @@ -221,10 +221,10 @@ using Serialization @test original_te_point ≈ reset_te_point atol=1e-4 end - @testset "First and Last Section Deformation with group_deform!" begin - # Create an ObjWing with a small number of panels and groups + @testset "First and Last Section Deformation with unrefined_deform!" begin + # Create an ObjWing with a small number of panels and unrefined sections wing = ObjWing(test_obj_path, test_dat_path; - n_panels=4, remove_nan=true) + n_panels=4, n_unrefined_sections=2, remove_nan=true) # Store original TE points from all refined_sections # Wing has n_panels+1 sections (5 sections for 4 panels) @@ -232,11 +232,11 @@ using Serialization original_te_points = [copy(wing.refined_sections[i].TE_point) for i in 1:n_sections] - # Apply group_deform! with non-zero angles (2 groups, each controlling 2 panels) + # Apply unrefined_deform! with non-zero angles (2 groups, each controlling 2 panels) theta_angles = [deg2rad(15.0), deg2rad(20.0)] delta_angles = [deg2rad(5.0), deg2rad(10.0)] - VortexStepMethod.group_deform!(wing, theta_angles, delta_angles; smooth=false) + VortexStepMethod.unrefined_deform!(wing, theta_angles, delta_angles; smooth=false) # Check that all sections' TE points have been deformed for i in 1:n_sections diff --git a/test/solver/test_group_coefficients.jl b/test/solver/test_group_coefficients.jl deleted file mode 100644 index 6bc6745e..00000000 --- a/test/solver/test_group_coefficients.jl +++ /dev/null @@ -1,148 +0,0 @@ -using VortexStepMethod -using LinearAlgebra -using Test - -@testset "Unrefined Coefficient Arrays Tests" begin - @testset "Unrefined coefficients aggregation" begin - # Create a simple wing with unrefined sections - n_panels = 20 - n_unrefined_sections = 5 # This gives 4 unrefined panels - - # Create a test wing settings file - settings_file = create_temp_wing_settings("solver", "solver_test_wing.yaml"; alpha=5.0, beta=0.0, wind_speed=10.0) - - try - # Modify settings to use specific panel configuration - settings = VSMSettings(settings_file) - settings.wings[1].n_panels = n_panels - settings.solver_settings.n_panels = n_panels - - # Create wing and solver - wing = Wing(settings) - body_aero = BodyAerodynamics([wing]) - solver = Solver(body_aero, settings) - - # Set conditions and solve - va = [10.0, 0.0, 0.0] - set_va!(body_aero, va) - sol = solve!(solver, body_aero) - - n_unrefined_panels = wing.n_unrefined_sections - 1 - - # Test 1: Unrefined arrays exist and have correct size - @test length(sol.cl_unrefined_array) == n_unrefined_panels - @test length(sol.cd_unrefined_array) == n_unrefined_panels - @test length(sol.cm_unrefined_array) == n_unrefined_panels - - # Test 2: Unrefined arrays are not all zeros (solver computed them) - @test !all(sol.cl_unrefined_array .== 0.0) - @test !all(sol.cd_unrefined_array .== 0.0) - - # Test 3: Verify unrefined coefficients are aggregated from refined panels - # using refined_panel_mapping - for unrefined_idx in 1:n_unrefined_panels - # Find all refined panels that map to this unrefined panel - refined_panel_indices = findall(x -> x == unrefined_idx, wing.refined_panel_mapping) - - if !isempty(refined_panel_indices) - # Calculate expected average from refined panel coefficients - expected_cl = sum(sol.cl_array[refined_panel_indices]) / length(refined_panel_indices) - expected_cd = sum(sol.cd_array[refined_panel_indices]) / length(refined_panel_indices) - expected_cm = sum(sol.cm_array[refined_panel_indices]) / length(refined_panel_indices) - - # Check if unrefined coefficients match expected averages - # Handle NaN values that can occur in INVISCID models - if isnan(expected_cl) - @test isnan(sol.cl_unrefined_array[unrefined_idx]) - else - @test isapprox(sol.cl_unrefined_array[unrefined_idx], expected_cl, rtol=1e-10) - end - if isnan(expected_cd) - @test isnan(sol.cd_unrefined_array[unrefined_idx]) - else - @test isapprox(sol.cd_unrefined_array[unrefined_idx], expected_cd, rtol=1e-10) - end - if isnan(expected_cm) - @test isnan(sol.cm_unrefined_array[unrefined_idx]) - else - @test isapprox(sol.cm_unrefined_array[unrefined_idx], expected_cm, rtol=1e-10) - end - end - end - - # Test 4: Verify physical consistency (lift coefficients should be positive at positive AoA) - # Skip test if values are NaN - if !any(isnan.(sol.cl_unrefined_array)) - @test all(sol.cl_unrefined_array .> 0.0) - end - - finally - rm(settings_file; force=true) - end - end - - @testset "Unrefined coefficients with different panel counts" begin - # Test with various panel/section combinations - test_cases = [ - (n_panels=40, n_unrefined_expected=21), # From YAML file sections - (n_panels=30, n_unrefined_expected=21), - (n_panels=24, n_unrefined_expected=21), - ] - - for (n_panels, n_unrefined_expected) in test_cases - settings_file = create_temp_wing_settings("solver", "solver_test_wing.yaml"; alpha=5.0, beta=0.0, wind_speed=10.0) - - try - settings = VSMSettings(settings_file) - settings.wings[1].n_panels = n_panels - settings.solver_settings.n_panels = n_panels - - wing = Wing(settings) - body_aero = BodyAerodynamics([wing]) - solver = Solver(body_aero, settings) - - va = [10.0, 0.0, 0.0] - set_va!(body_aero, va) - sol = solve!(solver, body_aero) - - n_unrefined_panels = wing.n_unrefined_sections - 1 - - # Verify arrays have correct size - @test length(sol.cl_unrefined_array) == n_unrefined_panels - @test length(sol.cd_unrefined_array) == n_unrefined_panels - @test length(sol.cm_unrefined_array) == n_unrefined_panels - - # Verify unrefined coefficients are computed correctly using mapping - for unrefined_idx in 1:n_unrefined_panels - refined_panel_indices = findall(x -> x == unrefined_idx, wing.refined_panel_mapping) - - if !isempty(refined_panel_indices) - expected_cl = sum(sol.cl_array[refined_panel_indices]) / length(refined_panel_indices) - expected_cd = sum(sol.cd_array[refined_panel_indices]) / length(refined_panel_indices) - expected_cm = sum(sol.cm_array[refined_panel_indices]) / length(refined_panel_indices) - - # Handle NaN for all coefficients - if isnan(expected_cl) - @test isnan(sol.cl_unrefined_array[unrefined_idx]) - else - @test isapprox(sol.cl_unrefined_array[unrefined_idx], expected_cl, rtol=1e-10) - end - if isnan(expected_cd) - @test isnan(sol.cd_unrefined_array[unrefined_idx]) - else - @test isapprox(sol.cd_unrefined_array[unrefined_idx], expected_cd, rtol=1e-10) - end - if isnan(expected_cm) - @test isnan(sol.cm_unrefined_array[unrefined_idx]) - else - @test isapprox(sol.cm_unrefined_array[unrefined_idx], expected_cm, rtol=1e-10) - end - end - end - - finally - rm(settings_file; force=true) - end - end - end -end diff --git a/test/test_data_utils.jl b/test/test_data_utils.jl index 23b54c59..13fc97ce 100644 --- a/test/test_data_utils.jl +++ b/test/test_data_utils.jl @@ -68,7 +68,6 @@ rm(settings_file) function create_temp_wing_settings(module_name, wing_file; name="test_wing", n_panels=4, - n_groups=2, spanwise_panel_distribution="COSINE", spanwise_direction=[0.0, 1.0, 0.0], remove_nan=true, @@ -87,7 +86,6 @@ function create_temp_wing_settings(module_name, wing_file; "name" => name, "geometry_file" => wing_file_path, "n_panels" => n_panels, - "n_groups" => n_groups, "spanwise_panel_distribution" => spanwise_panel_distribution, "spanwise_direction" => spanwise_direction, "remove_nan" => remove_nan, diff --git a/test/wing_geometry/test_wing_geometry.jl b/test/wing_geometry/test_wing_geometry.jl index 05458a64..5e458c2a 100644 --- a/test/wing_geometry/test_wing_geometry.jl +++ b/test/wing_geometry/test_wing_geometry.jl @@ -25,15 +25,15 @@ end @test example_wing.n_panels == 10 @test example_wing.spanwise_distribution == LINEAR @test example_wing.spanwise_direction ≈ [0.0, 1.0, 0.0] - @test length(example_wing.sections) == 0 + @test length(example_wing.unrefined_sections) == 0 end @testset "Add section" begin example_wing = Wing(10) add_section!(example_wing, [0.0, 0.0, 0.0], [-1.0, 0.0, 0.0], INVISCID) - @test length(example_wing.sections) == 1 + @test length(example_wing.unrefined_sections) == 1 - section = example_wing.sections[1] + section = example_wing.unrefined_sections[1] @test section.LE_point ≈ [0.0, 0.0, 0.0] @test section.TE_point ≈ [-1.0, 0.0, 0.0] @test section.aero_model === INVISCID @@ -57,7 +57,7 @@ end add_section!(wing, [0.0, 0.0, 0.0], [1.0, 0.0, 0.0], POLAR_VECTORS, aero_data) # Check if NaNs were removed consistently - cleaned_data = wing.sections[1].aero_data + cleaned_data = wing.unrefined_sections[1].aero_data @test length(cleaned_data[1]) == 18 # 21 - 3 NaN positions @test !any(isnan, cleaned_data[2]) # cl @test !any(isnan, cleaned_data[3]) # cd @@ -84,7 +84,7 @@ end add_section!(wing, [0.0, 0.0, 0.0], [1.0, 0.0, 0.0], POLAR_MATRICES, aero_data) # Check if NaNs were removed consistently - cleaned_data = wing.sections[1].aero_data + cleaned_data = wing.unrefined_sections[1].aero_data @test !any(isnan, cleaned_data[3]) # cl @test !any(isnan, cleaned_data[4]) # cd @test !any(isnan, cleaned_data[5]) # cm @@ -174,7 +174,7 @@ end add_section!(wing, [0.0, -span/2, 0.0], [-1.0, -span/2, 0.0], INVISCID) refine_aerodynamic_mesh!(wing) - sections = wing.sections + sections = wing.unrefined_sections @test length(sections) == wing.n_panels + 1 @test sections[1].LE_point ≈ [0.0, span/2, 0.0] @test sections[1].TE_point ≈ [-1.0, span/2, 0.0] @@ -351,7 +351,7 @@ end @test length(wing.refined_panel_mapping) == n_panels # Manually verify each refined panel is mapped to its closest unrefined panel - n_unrefined_panels = length(wing.sections) - 1 + n_unrefined_panels = length(wing.unrefined_sections) - 1 for refined_panel_idx in 1:n_panels # Calculate refined panel center le_mid = (wing.refined_sections[refined_panel_idx].LE_point + @@ -364,10 +364,10 @@ end min_dist = Inf closest_idx = 1 for unrefined_panel_idx in 1:n_unrefined_panels - le_mid_unref = (wing.sections[unrefined_panel_idx].LE_point + - wing.sections[unrefined_panel_idx+1].LE_point) / 2 - te_mid_unref = (wing.sections[unrefined_panel_idx].TE_point + - wing.sections[unrefined_panel_idx+1].TE_point) / 2 + le_mid_unref = (wing.unrefined_sections[unrefined_panel_idx].LE_point + + wing.unrefined_sections[unrefined_panel_idx+1].LE_point) / 2 + te_mid_unref = (wing.unrefined_sections[unrefined_panel_idx].TE_point + + wing.unrefined_sections[unrefined_panel_idx+1].TE_point) / 2 unrefined_center = (le_mid_unref + te_mid_unref) / 2 dist = norm(refined_center - unrefined_center) @@ -398,7 +398,7 @@ end @test length(wing.refined_panel_mapping) == n_panels # Verify each panel is mapped to its closest unrefined panel - n_unrefined_panels = length(wing.sections) - 1 + n_unrefined_panels = length(wing.unrefined_sections) - 1 for refined_panel_idx in 1:n_panels # Calculate refined panel center le_mid = (wing.refined_sections[refined_panel_idx].LE_point + @@ -411,10 +411,10 @@ end min_dist = Inf closest_idx = 1 for unrefined_panel_idx in 1:n_unrefined_panels - le_mid_unref = (wing.sections[unrefined_panel_idx].LE_point + - wing.sections[unrefined_panel_idx+1].LE_point) / 2 - te_mid_unref = (wing.sections[unrefined_panel_idx].TE_point + - wing.sections[unrefined_panel_idx+1].TE_point) / 2 + le_mid_unref = (wing.unrefined_sections[unrefined_panel_idx].LE_point + + wing.unrefined_sections[unrefined_panel_idx+1].LE_point) / 2 + te_mid_unref = (wing.unrefined_sections[unrefined_panel_idx].TE_point + + wing.unrefined_sections[unrefined_panel_idx+1].TE_point) / 2 unrefined_center = (le_mid_unref + te_mid_unref) / 2 dist = norm(refined_center - unrefined_center) @@ -444,7 +444,7 @@ end @test length(wing.refined_panel_mapping) == n_panels # Verify each panel is mapped to its closest unrefined panel - n_unrefined_panels = length(wing.sections) - 1 + n_unrefined_panels = length(wing.unrefined_sections) - 1 for refined_panel_idx in 1:n_panels # Calculate refined panel center le_mid = (wing.refined_sections[refined_panel_idx].LE_point + @@ -457,10 +457,10 @@ end min_dist = Inf closest_idx = 1 for unrefined_panel_idx in 1:n_unrefined_panels - le_mid_unref = (wing.sections[unrefined_panel_idx].LE_point + - wing.sections[unrefined_panel_idx+1].LE_point) / 2 - te_mid_unref = (wing.sections[unrefined_panel_idx].TE_point + - wing.sections[unrefined_panel_idx+1].TE_point) / 2 + le_mid_unref = (wing.unrefined_sections[unrefined_panel_idx].LE_point + + wing.unrefined_sections[unrefined_panel_idx+1].LE_point) / 2 + te_mid_unref = (wing.unrefined_sections[unrefined_panel_idx].TE_point + + wing.unrefined_sections[unrefined_panel_idx+1].TE_point) / 2 unrefined_center = (le_mid_unref + te_mid_unref) / 2 dist = norm(refined_center - unrefined_center) diff --git a/test/yaml_geometry/test_wing_constructor.jl b/test/yaml_geometry/test_wing_constructor.jl index 87a1ab8e..e0acf4a9 100644 --- a/test/yaml_geometry/test_wing_constructor.jl +++ b/test/yaml_geometry/test_wing_constructor.jl @@ -37,31 +37,31 @@ using Logging # Use the actual YAML file from the test data cp(test_data_path("yaml_geometry", "simple_wing.yaml"), test_yaml_path; force=true) - wing = Wing(test_yaml_path; n_panels=4, # n_groups=2) - + wing = Wing(test_yaml_path; n_panels=4) + @test wing isa Wing @test wing.n_panels == 4 - @test wing.n_unrefined_sections - 1 == 2 + @test wing.n_unrefined_sections == 2 @test wing.spanwise_distribution == LINEAR @test wing.spanwise_direction ≈ [0.0, 1.0, 0.0] - @test length(wing.sections) == 2 # simple_wing has 2 sections + @test length(wing.unrefined_sections) == 2 # simple_wing has 2 sections # Test section coordinates (sections are sorted by spanwise position) # simple_wing.yaml has: [1, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0] and [1, 0.0, -1.0, 0.0, 1.0, -1.0, 0.0] # Sorted by y-coordinate: y=1.0, y=-1.0 - @test wing.sections[1].LE_point ≈ [0.0, 1.0, 0.0] - @test wing.sections[1].TE_point ≈ [1.0, 1.0, 0.0] - @test wing.sections[2].LE_point ≈ [0.0, -1.0, 0.0] - @test wing.sections[2].TE_point ≈ [1.0, -1.0, 0.0] + @test wing.unrefined_sections[1].LE_point ≈ [0.0, 1.0, 0.0] + @test wing.unrefined_sections[1].TE_point ≈ [1.0, 1.0, 0.0] + @test wing.unrefined_sections[2].LE_point ≈ [0.0, -1.0, 0.0] + @test wing.unrefined_sections[2].TE_point ≈ [1.0, -1.0, 0.0] # Test that sections have polar data - @test wing.sections[1].aero_model == POLAR_VECTORS - @test wing.sections[2].aero_model == POLAR_VECTORS + @test wing.unrefined_sections[1].aero_model == POLAR_VECTORS + @test wing.unrefined_sections[2].aero_model == POLAR_VECTORS # Test polar data is loaded - @test wing.sections[1].aero_data isa Tuple - @test length(wing.sections[1].aero_data) == 4 - @test length(wing.sections[1].aero_data[1]) >= 3 # at least 3 alpha points + @test wing.unrefined_sections[1].aero_data isa Tuple + @test length(wing.unrefined_sections[1].aero_data) == 4 + @test length(wing.unrefined_sections[1].aero_data[1]) >= 3 # at least 3 alpha points end @testset "Wing Constructor Parameters" begin @@ -72,13 +72,12 @@ using Logging wing = Wing( test_yaml_path; n_panels=8, - # n_groups=4, spanwise_distribution=COSINE, remove_nan=false ) - + @test wing.n_panels == 8 - @test wing.n_unrefined_sections - 1 == 4 + @test wing.n_unrefined_sections == 2 @test wing.spanwise_distribution == COSINE @test !wing.remove_nan end @@ -104,8 +103,8 @@ wing_airfoils: wing = suppress_warnings(() -> Wing(test_yaml_path; n_panels=2)) # Should fall back to INVISCID model - @test wing.sections[1].aero_model == INVISCID - @test wing.sections[1].aero_data === nothing + @test wing.unrefined_sections[1].aero_model == INVISCID + @test wing.unrefined_sections[1].aero_data === nothing end @testset "Sections Without Polar Files" begin @@ -129,7 +128,7 @@ wing_airfoils: wing = suppress_warnings(() -> Wing(test_yaml_path; n_panels=2)) # Should fall back to INVISCID model - @test wing.sections[1].aero_model == INVISCID + @test wing.unrefined_sections[1].aero_model == INVISCID end @testset "Invalid Parameters" begin @@ -148,13 +147,9 @@ wing_airfoils: - [1, polars, {csv_file_path: "polars/1.csv"}] """ write(test_yaml_path, yaml_content) - - # Test invalid n_panels/n_groups combination - @test_throws ArgumentError Wing(test_yaml_path; n_panels=5, # n_groups=2) - # Test # n_groups=0 (no grouping functionality) - wing_no_groups = Wing(test_yaml_path; n_panels=4, # n_groups=0) - @test wing_no_groups.n_groups == 0 + # Test # n_groups=0 (no grouping functionality) - backward compatibility + wing_no_groups = Wing(test_yaml_path; n_panels=4) @test wing_no_groups.n_panels == 4 # Test invalid spanwise direction @@ -177,10 +172,10 @@ wing_airfoils: wing = Wing(subdir_yaml_path; n_panels=2) # Should successfully load polar data with relative path - @test wing.sections[1].aero_model == POLAR_VECTORS - @test wing.sections[1].aero_data isa Tuple - @test wing.sections[2].aero_model == POLAR_VECTORS - @test wing.sections[2].aero_data isa Tuple + @test wing.unrefined_sections[1].aero_model == POLAR_VECTORS + @test wing.unrefined_sections[1].aero_data isa Tuple + @test wing.unrefined_sections[2].aero_model == POLAR_VECTORS + @test wing.unrefined_sections[2].aero_data isa Tuple # Cleanup rm(subdir; recursive=true) @@ -189,21 +184,21 @@ wing_airfoils: @testset "Complex Wing Geometry" begin # Use the actual complex_wing.yaml file cp(test_data_path("yaml_geometry", "complex_wing.yaml"), test_yaml_path; force=true) - - wing = Wing(test_yaml_path; n_panels=12, # n_groups=3) - + + wing = Wing(test_yaml_path; n_panels=12) + @test wing.n_panels == 12 - @test wing.n_unrefined_sections - 1 == 3 - @test length(wing.sections) == 7 + @test wing.n_unrefined_sections == 7 + @test length(wing.unrefined_sections) == 7 # Test that different airfoil_ids get different polar data - @test wing.sections[1].aero_model == POLAR_VECTORS - @test wing.sections[2].aero_model == POLAR_VECTORS + @test wing.unrefined_sections[1].aero_model == POLAR_VECTORS + @test wing.unrefined_sections[2].aero_model == POLAR_VECTORS # Verify geometric progression along wingspan - @test wing.sections[1].LE_point[2] == 5.0 # First section at y=5 - @test wing.sections[4].LE_point[2] == 0.0 # Middle section at y=0 - @test wing.sections[7].LE_point[2] == -5.0 # Last section at y=-5 + @test wing.unrefined_sections[1].LE_point[2] == 5.0 # First section at y=5 + @test wing.unrefined_sections[4].LE_point[2] == 0.0 # Middle section at y=0 + @test wing.unrefined_sections[7].LE_point[2] == -5.0 # Last section at y=-5 end @testset "VSMSettings Constructor" begin @@ -216,20 +211,19 @@ wing_airfoils: settings.wings = [WingSettings( geometry_file=simple_wing_file, n_panels=6, - # n_groups=3, spanwise_panel_distribution=COSINE )] - + # Test Wing constructor with VSMSettings wing = Wing(settings) - + @test wing isa Wing @test wing.n_panels == 6 - @test wing.n_unrefined_sections - 1 == 3 + @test wing.n_unrefined_sections == 2 @test wing.spanwise_distribution == COSINE - @test length(wing.sections) == 2 - @test wing.sections[1].aero_model == POLAR_VECTORS - @test wing.sections[2].aero_model == POLAR_VECTORS + @test length(wing.unrefined_sections) == 2 + @test wing.unrefined_sections[1].aero_model == POLAR_VECTORS + @test wing.unrefined_sections[2].aero_model == POLAR_VECTORS end @testset "Shared Test Data Usage" begin @@ -238,33 +232,33 @@ wing_airfoils: @test isfile(simple_wing_file) # Test basic Wing construction with shared data - wing = Wing(simple_wing_file; n_panels=4, # n_groups=2) + wing = Wing(simple_wing_file; n_panels=4) @test wing isa Wing @test wing.n_panels == 4 - @test wing.n_unrefined_sections - 1 == 2 - @test length(wing.sections) == 2 + @test wing.n_unrefined_sections == 2 + @test length(wing.unrefined_sections) == 2 # Test complex wing construction complex_wing_file = test_data_path("yaml_geometry", "complex_wing.yaml") @test isfile(complex_wing_file) - complex_wing = Wing(complex_wing_file; n_panels=12, # n_groups=3) + complex_wing = Wing(complex_wing_file; n_panels=12) @test complex_wing isa Wing @test complex_wing.n_panels == 12 - @test complex_wing.n_groups == 3 - @test length(complex_wing.sections) == 7 + @test complex_wing.n_unrefined_sections == 7 + @test length(complex_wing.unrefined_sections) == 7 # Verify polar data is loaded from shared files - @test complex_wing.sections[1].aero_model == POLAR_VECTORS - @test complex_wing.sections[1].aero_data isa Tuple + @test complex_wing.unrefined_sections[1].aero_model == POLAR_VECTORS + @test complex_wing.unrefined_sections[1].aero_data isa Tuple # Test with module-specific convenience function - create a standard wing for this test standard_wing_file = simple_wing_file # Use simple_wing as our "standard" @test isfile(standard_wing_file) - standard_wing = Wing(standard_wing_file; n_panels=2, # n_groups=1) + standard_wing = Wing(standard_wing_file; n_panels=2) @test standard_wing isa Wing - @test length(standard_wing.sections) == 2 + @test length(standard_wing.unrefined_sections) == 2 end # Cleanup after all tests diff --git a/test/yaml_geometry/test_yaml_wing_deformation.jl b/test/yaml_geometry/test_yaml_wing_deformation.jl index ac51e243..4b434de7 100644 --- a/test/yaml_geometry/test_yaml_wing_deformation.jl +++ b/test/yaml_geometry/test_yaml_wing_deformation.jl @@ -6,7 +6,7 @@ using Test @testset "Simple Wing Deformation" begin # Load existing simple_wing.yaml simple_wing_file = test_data_path("yaml_geometry", "simple_wing.yaml") - wing = Wing(simple_wing_file; n_panels=4, # n_groups=2) + wing = Wing(simple_wing_file; n_panels=4) body_aero = BodyAerodynamics([wing]) # Store original TE point for comparison @@ -15,8 +15,8 @@ using Test original_le_point = copy(body_aero.panels[i].LE_point_1) # Apply deformation with non-zero angles - theta_dist = fill(deg2rad(30.0), wing.n_panels) # 30 degrees twist - delta_dist = fill(deg2rad(5.0), wing.n_panels) # 5 degrees trailing edge deflection + theta_dist = fill(deg2rad(30.0), wing.n_unrefined_sections) # 30 degrees twist + delta_dist = fill(deg2rad(5.0), wing.n_unrefined_sections) # 5 degrees trailing edge deflection VortexStepMethod.deform!(wing, theta_dist, delta_dist) VortexStepMethod.reinit!(body_aero; refine_mesh=false) @@ -36,8 +36,8 @@ using Test @test body_aero.panels[i].delta ≈ deg2rad(5.0) # Reset deformation with zero angles - zero_theta_dist = zeros(wing.n_panels) - zero_delta_dist = zeros(wing.n_panels) + zero_theta_dist = zeros(wing.n_unrefined_sections) + zero_delta_dist = zeros(wing.n_unrefined_sections) VortexStepMethod.deform!(wing, zero_theta_dist, zero_delta_dist) VortexStepMethod.reinit!(body_aero; refine_mesh=false) @@ -53,7 +53,7 @@ using Test @testset "Complex Wing Deformation" begin # Load existing complex_wing.yaml with multiple sections complex_wing_file = test_data_path("yaml_geometry", "complex_wing.yaml") - wing = Wing(complex_wing_file; n_panels=12, # n_groups=3) + wing = Wing(complex_wing_file; n_panels=12) body_aero = BodyAerodynamics([wing]) # Store original points for multiple panels @@ -67,8 +67,9 @@ using Test end # Apply spanwise-varying deformation - theta_dist = [deg2rad(10.0 * i / wing.n_panels) for i in 1:wing.n_panels] # Linear twist distribution - delta_dist = [deg2rad(-5.0 + 10.0 * i / wing.n_panels) for i in 1:wing.n_panels] # Varying deflection + n = wing.n_unrefined_sections + theta_dist = [deg2rad(10.0 * i / n) for i in 1:n] # Linear twist distribution + delta_dist = [deg2rad(-5.0 + 10.0 * i / n) for i in 1:n] # Varying deflection VortexStepMethod.deform!(wing, theta_dist, delta_dist) VortexStepMethod.reinit!(body_aero; refine_mesh=false) @@ -89,7 +90,7 @@ using Test @test body_aero.panels[1].delta < body_aero.panels[end].delta # Reset and verify - VortexStepMethod.deform!(wing, zeros(wing.n_panels), zeros(wing.n_panels)) + VortexStepMethod.deform!(wing, zeros(wing.n_unrefined_sections), zeros(wing.n_unrefined_sections)) VortexStepMethod.reinit!(body_aero; refine_mesh=false) for (idx, i) in enumerate(test_indices) @@ -104,11 +105,11 @@ using Test @testset "Multiple Reinit Calls with NTuple aero_data" begin # This test specifically checks the NTuple handling fix simple_wing_file = test_data_path("yaml_geometry", "simple_wing.yaml") - wing = Wing(simple_wing_file; n_panels=4, # n_groups=2) + wing = Wing(simple_wing_file; n_panels=4) # Verify that sections have NTuple aero_data (for wings with simple polars) # or other valid AeroData types - @test wing.sections[1].aero_data !== nothing + @test wing.unrefined_sections[1].aero_data !== nothing # Perform multiple reinit! calls to ensure NTuple handling works for _ in 1:5 @@ -116,7 +117,7 @@ using Test end # Wing should still be valid after multiple reinits - @test wing.sections[1].aero_data !== nothing + @test wing.unrefined_sections[1].aero_data !== nothing # Verify refined_sections and non_deformed_sections are properly populated @test length(wing.refined_sections) == wing.n_panels + 1 @test length(wing.non_deformed_sections) == wing.n_panels + 1 @@ -125,12 +126,12 @@ using Test @testset "Deformation with BodyAerodynamics Reinit" begin # Test that reinit! on BodyAerodynamics properly handles deformed wings simple_wing_file = test_data_path("yaml_geometry", "simple_wing.yaml") - wing = Wing(simple_wing_file; n_panels=4, # n_groups=2) + wing = Wing(simple_wing_file; n_panels=4) body_aero = BodyAerodynamics([wing]) # Apply deformation - theta_dist = fill(deg2rad(15.0), wing.n_panels) - delta_dist = fill(deg2rad(3.0), wing.n_panels) + theta_dist = fill(deg2rad(15.0), wing.n_unrefined_sections) + delta_dist = fill(deg2rad(3.0), wing.n_unrefined_sections) VortexStepMethod.deform!(wing, theta_dist, delta_dist) VortexStepMethod.reinit!(body_aero; refine_mesh=false) @@ -153,17 +154,17 @@ using Test @testset "Edge Cases" begin simple_wing_file = test_data_path("yaml_geometry", "simple_wing.yaml") - wing = Wing(simple_wing_file; n_panels=2, # n_groups=1) + wing = Wing(simple_wing_file; n_panels=2) body_aero = BodyAerodynamics([wing]) # Test zero deformation - VortexStepMethod.deform!(wing, zeros(wing.n_panels), zeros(wing.n_panels)) + VortexStepMethod.deform!(wing, zeros(wing.n_unrefined_sections), zeros(wing.n_unrefined_sections)) VortexStepMethod.reinit!(body_aero; refine_mesh=false) @test all(p.delta ≈ 0.0 for p in body_aero.panels) # Test large deformation angles - theta_dist = fill(deg2rad(60.0), wing.n_panels) - delta_dist = fill(deg2rad(30.0), wing.n_panels) + theta_dist = fill(deg2rad(60.0), wing.n_unrefined_sections) + delta_dist = fill(deg2rad(30.0), wing.n_unrefined_sections) # Should not error even with large angles VortexStepMethod.deform!(wing, theta_dist, delta_dist) @@ -171,8 +172,8 @@ using Test @test all(p.delta ≈ deg2rad(30.0) for p in body_aero.panels) # Test negative angles - theta_dist = fill(deg2rad(-20.0), wing.n_panels) - delta_dist = fill(deg2rad(-10.0), wing.n_panels) + theta_dist = fill(deg2rad(-20.0), wing.n_unrefined_sections) + delta_dist = fill(deg2rad(-10.0), wing.n_unrefined_sections) VortexStepMethod.deform!(wing, theta_dist, delta_dist) VortexStepMethod.reinit!(body_aero; refine_mesh=false) @test all(p.delta ≈ deg2rad(-10.0) for p in body_aero.panels) From 860f38d0550d140584d70b1b852eec2e6538d3db Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sat, 6 Dec 2025 13:15:35 +0100 Subject: [PATCH 34/86] Dist for per panel, unrefined_dist for per unrefined section --- src/body_aerodynamics.jl | 32 ++-- src/solver.jl | 320 +++++++++++++++++++-------------------- 2 files changed, 176 insertions(+), 176 deletions(-) diff --git a/src/body_aerodynamics.jl b/src/body_aerodynamics.jl index 6b3ed591..539c95f9 100644 --- a/src/body_aerodynamics.jl +++ b/src/body_aerodynamics.jl @@ -13,8 +13,8 @@ Main structure for calculating aerodynamic properties of bodies. Use the constru - `alpha_uncorrected`=zeros(Float64, P): angles of attack per panel - `alpha_corrected`=zeros(Float64, P): corrected angles of attack per panel - `stall_angle_list`=zeros(Float64, P): stall angle per panel -- `alpha_array::MVector{P, Float64}` = zeros(Float64, P) -- `v_a_array::MVector{P, Float64}` = zeros(Float64, P) +- `alpha_dist::MVector{P, Float64}` = zeros(Float64, P) +- `v_a_dist::MVector{P, Float64}` = zeros(Float64, P) - `work_vectors`::NTuple{10, MVec3} = ntuple(_ -> zeros(MVec3), 10) - `AIC::Array{Float64, 3}` = zeros(3, P, P) - `projected_area::Float64` = 1.0: The area projected onto the xy-plane of the kite body reference frame [m²] @@ -30,8 +30,8 @@ Main structure for calculating aerodynamic properties of bodies. Use the constru alpha_uncorrected::MVector{P, Float64} = zeros(P) alpha_corrected::MVector{P, Float64} = zeros(P) stall_angle_list::MVector{P, Float64} = zeros(P) - alpha_array::MVector{P, Float64} = zeros(P) - v_a_array::MVector{P, Float64} = zeros(P) + alpha_dist::MVector{P, Float64} = zeros(P) + v_a_dist::MVector{P, Float64} = zeros(P) work_vectors::NTuple{10,MVec3} = ntuple(_ -> zeros(MVec3), 10) AIC::Array{Float64, 3} = zeros(3, P, P) projected_area::Float64 = one(Float64) @@ -186,8 +186,8 @@ function reinit!(body_aero::BodyAerodynamics; # Initialize rest of the struct body_aero.projected_area = sum(calculate_projected_area, body_aero.wings) calculate_stall_angle_list!(body_aero.stall_angle_list, body_aero.panels) - body_aero.alpha_array .= 0.0 - body_aero.v_a_array .= 0.0 + body_aero.alpha_dist .= 0.0 + body_aero.v_a_dist .= 0.0 body_aero.AIC .= 0.0 set_va!(body_aero, va, omega) return nothing @@ -418,7 +418,7 @@ end calculate_results(body_aero::BodyAerodynamics, gamma_new, density, aerodynamic_model_type::Model, core_radius_fraction, mu, - alpha_array, v_a_array, + alpha_dist, v_a_dist, chord_array, x_airf_array, y_airf_array, z_airf_array, va_array, va_norm_array, @@ -438,8 +438,8 @@ function calculate_results( aerodynamic_model_type::Model, core_radius_fraction, mu, - alpha_array, - v_a_array, + alpha_dist, + v_a_dist, chord_array, x_airf_array, y_airf_array, @@ -462,15 +462,15 @@ function calculate_results( # Calculate coefficients for each panel for (i, panel) in enumerate(panels) - cl_array[i] = calculate_cl(panel, alpha_array[i]) - cd_array[i], cm_array[i] = calculate_cd_cm(panel, alpha_array[i]) + cl_array[i] = calculate_cl(panel, alpha_dist[i]) + cd_array[i], cm_array[i] = calculate_cd_cm(panel, alpha_dist[i]) panel_width_array[i] = panel.width end # Calculate forces - lift = reshape((cl_array .* 0.5 .* density .* v_a_array.^2 .* chord_array), :, 1) - drag = reshape((cd_array .* 0.5 .* density .* v_a_array.^2 .* chord_array), :, 1) - moment = reshape((cm_array .* 0.5 .* density .* v_a_array.^2 .* chord_array), :, 1) + lift = reshape((cl_array .* 0.5 .* density .* v_a_dist.^2 .* chord_array), :, 1) + drag = reshape((cd_array .* 0.5 .* density .* v_a_dist.^2 .* chord_array), :, 1) + moment = reshape((cm_array .* 0.5 .* density .* v_a_dist.^2 .* chord_array), :, 1) # Calculate alpha corrections based on model type if correct_aoa @@ -486,7 +486,7 @@ function calculate_results( va_unit_array ) else - alpha_corrected .= alpha_array + alpha_corrected .= alpha_dist end # Verify va is not distributed @@ -632,7 +632,7 @@ function calculate_results( "cfy" => (sum(f_body_3D[2,:]) / (q_inf * projected_area)), "cfz" => (sum(f_body_3D[3,:]) / (q_inf * projected_area)), "alpha_at_ac" => alpha_corrected, - "alpha_uncorrected" => alpha_array, + "alpha_uncorrected" => alpha_dist, "alpha_geometric" => alpha_geometric, "gamma_distribution" => gamma_new, "area_all_panels" => area_all_panels, diff --git a/src/solver.jl b/src/solver.jl index 111e2cea..3ec3c376 100644 --- a/src/solver.jl +++ b/src/solver.jl @@ -4,15 +4,19 @@ Struct for storing the solution of the [solve!](@ref) function. Must contain all info needed by `KiteModels.jl`. +# Naming Convention +- Variables ending in `_dist`: Per-panel distributions (length P, one value per panel) +- Variables ending in `_unrefined_dist`: Per-unrefined-section distributions (length U, averaged values per unrefined section) + # Attributes -- `panel_width_array`::Vector{Float64}: Width of the panels [m] -- `alpha_array`::Vector{Float64}: Angle of attack of each panel relative to the apparent wind [rad] -- cl_array::Vector{Float64}: Lift coefficients of the panels [-] -- cd_array::Vector{Float64}: Drag coefficients of the panels [-] -- cm_array::Vector{Float64}: Pitching moment coefficients of the panels [-] -- panel_lift::Vector{Float64}: Lift force of the panels [N] -- panel_drag::Vector{Float64}: Drag force of the panels [N] -- panel_moment::Vector{Float64}: Pitching moment around the spanwise vector of the panels [Nm] +- `width_dist`::Vector{Float64}: Width of the panels [m] +- `alpha_dist`::Vector{Float64}: Angle of attack of each panel relative to the apparent wind [rad] +- cl_dist::Vector{Float64}: Lift coefficients of the panels [-] +- cd_dist::Vector{Float64}: Drag coefficients of the panels [-] +- cm_dist::Vector{Float64}: Pitching moment coefficients of the panels [-] +- lift_dist::Vector{Float64}: Lift force of the panels [N] +- drag_dist::Vector{Float64}: Drag force of the panels [N] +- panel_moment_dist::Vector{Float64}: Pitching moment around the spanwise vector of the panels [Nm] - `f_body_3D`::Matrix{Float64}: Matrix of the aerodynamic forces (x, y, z vectors) [N] - `m_body_3D`::Matrix{Float64}: Matrix of the aerodynamic moments [Nm] - `gamma_distribution`::Union{Nothing, Vector{Float64}}: Vector containing the panel circulations. @@ -22,30 +26,29 @@ Struct for storing the solution of the [solve!](@ref) function. Must contain all - `moment_coeffs`::MVec3: Aerodynamic moment coefficients [CMx, CMy, CMz] [-] - `moment_dist`::Vector{Float64}: Pitching moments around the spanwise vector of each panel. [Nm] - `moment_coeff_dist`::Vector{Float64}: Pitching moment coefficient around the spanwise vector of each panel. [-] -- `unrefined_moment_dist`::MVector{U, Float64}: Aggregated moments for unrefined sections [Nm] -- `unrefined_moment_coeff_dist`::MVector{U, Float64}: Aggregated moment coefficients for unrefined sections [-] -- `cl_unrefined_array`::MVector{U, Float64}: Averaged lift coefficients for unrefined sections [-] -- `cd_unrefined_array`::MVector{U, Float64}: Averaged drag coefficients for unrefined sections [-] -- `cm_unrefined_array`::MVector{U, Float64}: Averaged moment coefficients for unrefined sections [-] -- `alpha_unrefined_array`::MVector{U, Float64}: Averaged angles of attack for unrefined sections [rad] +- `moment_unrefined_dist`::MVector{U, Float64}: Averaged moments for unrefined sections [Nm] +- `cl_unrefined_dist`::MVector{U, Float64}: Averaged lift coefficients for unrefined sections [-] +- `cd_unrefined_dist`::MVector{U, Float64}: Averaged drag coefficients for unrefined sections [-] +- `cm_unrefined_dist`::MVector{U, Float64}: Averaged moment coefficients for unrefined sections [-] +- `alpha_unrefined_dist`::MVector{U, Float64}: Averaged angles of attack for unrefined sections [rad] - `solver_status`::SolverStatus: enum, see [SolverStatus](@ref) """ @with_kw mutable struct VSMSolution{P,U} ### private vectors of solve_base! - _x_airf_array::Matrix{Float64} = zeros(P, 3) - _y_airf_array::Matrix{Float64} = zeros(P, 3) - _z_airf_array::Matrix{Float64} = zeros(P, 3) - _va_array::Matrix{Float64} = zeros(P, 3) - _chord_array::Vector{Float64} = zeros(P) + _x_airf_dist::Matrix{Float64} = zeros(P, 3) + _y_airf_dist::Matrix{Float64} = zeros(P, 3) + _z_airf_dist::Matrix{Float64} = zeros(P, 3) + _va_dist::Matrix{Float64} = zeros(P, 3) + _chord_dist::Vector{Float64} = zeros(P) ### end of private vectors - panel_width_array::Vector{Float64} = zeros(P) - alpha_array::Vector{Float64} = zeros(P) - cl_array::Vector{Float64} = zeros(P) - cd_array::Vector{Float64} = zeros(P) - cm_array::Vector{Float64} = zeros(P) - panel_lift::Vector{Float64} = zeros(P) - panel_drag::Vector{Float64} = zeros(P) - panel_moment::Vector{Float64} = zeros(P) + width_dist::Vector{Float64} = zeros(P) + alpha_dist::Vector{Float64} = zeros(P) + cl_dist::Vector{Float64} = zeros(P) + cd_dist::Vector{Float64} = zeros(P) + cm_dist::Vector{Float64} = zeros(P) + lift_dist::Vector{Float64} = zeros(P) + drag_dist::Vector{Float64} = zeros(P) + panel_moment_dist::Vector{Float64} = zeros(P) f_body_3D::Matrix{Float64} = zeros(3, P) m_body_3D::Matrix{Float64} = zeros(3, P) gamma_distribution::Union{Nothing, Vector{Float64}} = nothing @@ -55,18 +58,17 @@ Struct for storing the solution of the [solve!](@ref) function. Must contain all moment_coeffs::MVec3 = zeros(MVec3) moment_dist::MVector{P, Float64} = zeros(P) moment_coeff_dist::MVector{P, Float64} = zeros(P) - unrefined_moment_dist::MVector{U, Float64} = zeros(U) - unrefined_moment_coeff_dist::MVector{U, Float64} = zeros(U) - cl_unrefined_array::MVector{U, Float64} = zeros(U) - cd_unrefined_array::MVector{U, Float64} = zeros(U) - cm_unrefined_array::MVector{U, Float64} = zeros(U) - alpha_unrefined_array::MVector{U, Float64} = zeros(U) - x_airf_unrefined_array::Vector{MVec3} = [MVec3(0,0,0) for _ in 1:U] - y_airf_unrefined_array::Vector{MVec3} = [MVec3(0,0,0) for _ in 1:U] - z_airf_unrefined_array::Vector{MVec3} = [MVec3(0,0,0) for _ in 1:U] - va_unrefined_array::Vector{MVec3} = [MVec3(0,0,0) for _ in 1:U] - chord_unrefined_array::MVector{U, Float64} = zeros(U) - width_unrefined_array::MVector{U, Float64} = zeros(U) + moment_unrefined_dist::MVector{U, Float64} = zeros(U) + cl_unrefined_dist::MVector{U, Float64} = zeros(U) + cd_unrefined_dist::MVector{U, Float64} = zeros(U) + cm_unrefined_dist::MVector{U, Float64} = zeros(U) + alpha_unrefined_dist::MVector{U, Float64} = zeros(U) + x_airf_unrefined_dist::Vector{MVec3} = [MVec3(0,0,0) for _ in 1:U] + y_airf_unrefined_dist::Vector{MVec3} = [MVec3(0,0,0) for _ in 1:U] + z_airf_unrefined_dist::Vector{MVec3} = [MVec3(0,0,0) for _ in 1:U] + va_unrefined_dist::Vector{MVec3} = [MVec3(0,0,0) for _ in 1:U] + chord_unrefined_dist::MVector{U, Float64} = zeros(U) + width_unrefined_dist::MVector{U, Float64} = zeros(U) solver_status::SolverStatus = FAILURE end @@ -74,13 +76,13 @@ end @with_kw mutable struct LoopResult{P} converged::Bool = false gamma_new::MVector{P, Float64} = zeros(P) - alpha_array::MVector{P, Float64} = zeros(P) # TODO: Is this different from BodyAerodynamics.alpha_array ? - v_a_array::MVector{P, Float64} = zeros(P) + alpha_dist::MVector{P, Float64} = zeros(P) # TODO: Is this different from BodyAerodynamics.alpha_dist ? + v_a_dist::MVector{P, Float64} = zeros(P) end @with_kw struct BaseResult{P} - va_norm_array::MVector{P, Float64} = zeros(P) - va_unit_array::Matrix{Float64} = zeros(P, 3) + va_norm_dist::MVector{P, Float64} = zeros(P) + va_unit_dist::Matrix{Float64} = zeros(P, 3) end """ @@ -200,16 +202,16 @@ function solve!(solver::Solver, body_aero::BodyAerodynamics, gamma_distribution= end # Initialize arrays - cl_array = solver.sol.cl_array - cd_array = solver.sol.cd_array - cm_array = solver.sol.cm_array + cl_dist = solver.sol.cl_dist + cd_dist = solver.sol.cd_dist + cm_dist = solver.sol.cm_dist converged = solver.lr.converged - alpha_array = solver.lr.alpha_array - alpha_corrected = solver.sol.alpha_array - v_a_array = solver.lr.v_a_array + alpha_dist = solver.lr.alpha_dist + alpha_corrected = solver.sol.alpha_dist + v_a_dist = solver.lr.v_a_dist panels = body_aero.panels - panel_width_array = solver.sol.panel_width_array + width_dist = solver.sol.width_dist solver.sol.moment_dist .= 0 solver.sol.moment_coeff_dist .= 0 moment_dist = solver.sol.moment_dist @@ -219,20 +221,20 @@ function solve!(solver::Solver, body_aero::BodyAerodynamics, gamma_distribution= # Calculate coefficients for each panel for (i, panel) in enumerate(panels) # zero bytes - cl_array[i] = calculate_cl(panel, alpha_array[i]) - cd_array[i], cm_array[i] = calculate_cd_cm(panel, alpha_array[i]) - panel_width_array[i] = panel.width + cl_dist[i] = calculate_cl(panel, alpha_dist[i]) + cd_dist[i], cm_dist[i] = calculate_cd_cm(panel, alpha_dist[i]) + width_dist[i] = panel.width end # create an alias for the three vertical output vectors - lift = solver.sol.panel_lift - drag = solver.sol.panel_drag - panel_moment = solver.sol.panel_moment + lift = solver.sol.lift_dist + drag = solver.sol.drag_dist + panel_moment_dist = solver.sol.panel_moment_dist # Compute using fused broadcasting (no intermediate allocations) - @. lift = cl_array * 0.5 * density * v_a_array^2 * solver.sol._chord_array - @. drag = cd_array * 0.5 * density * v_a_array^2 * solver.sol._chord_array - @. panel_moment = cm_array * 0.5 * density * v_a_array^2 * solver.sol._chord_array + @. lift = cl_dist * 0.5 * density * v_a_dist^2 * solver.sol._chord_dist + @. drag = cd_dist * 0.5 * density * v_a_dist^2 * solver.sol._chord_dist + @. panel_moment_dist = cm_dist * 0.5 * density * v_a_dist^2 * solver.sol._chord_dist # Calculate alpha corrections based on model type if aerodynamic_model_type == VSM # 64 bytes @@ -241,14 +243,14 @@ function solve!(solver::Solver, body_aero::BodyAerodynamics, gamma_distribution= body_aero, gamma_new, solver.core_radius_fraction, - solver.sol._z_airf_array, - solver.sol._x_airf_array, - solver.sol._va_array, - solver.br.va_norm_array, - solver.br.va_unit_array + solver.sol._z_airf_dist, + solver.sol._x_airf_dist, + solver.sol._va_dist, + solver.br.va_norm_dist, + solver.br.va_unit_dist ) elseif aerodynamic_model_type == LLT - alpha_corrected .= alpha_array + alpha_corrected .= alpha_dist end # Initialize result arrays @@ -296,7 +298,7 @@ function solve!(solver::Solver, body_aero::BodyAerodynamics, gamma_distribution= # Use the axis around which the moment is defined, # which is the y-axis pointing "spanwise" moment_axis_body = panel.y_airf - M_local_3D = panel_moment[i] * moment_axis_body * panel.width + M_local_3D = panel_moment_dist[i] * moment_axis_body * panel.width # Vector from panel AC to the chosen reference point: r_vector = panel_ac_body - reference_point # e.g. CG, wing root, etc. # Cross product to shift the force from panel AC to ref. point: @@ -306,40 +308,38 @@ function solve!(solver::Solver, body_aero::BodyAerodynamics, gamma_distribution= # Calculate the moment distribution (moment on each panel) arm = (moment_frac - 0.25) * panel.chord - moment_dist[i] = ((ftotal_induced_va ⋅ panel.z_airf) * arm + panel_moment[i]) * panel.width + moment_dist[i] = ((ftotal_induced_va ⋅ panel.z_airf) * arm + panel_moment_dist[i]) * panel.width moment_coeff_dist[i] = moment_dist[i] / (q_inf * projected_area) end # Only compute unrefined arrays if there are unrefined sections - if length(solver.sol.unrefined_moment_dist) > 0 - unrefined_moment_dist = solver.sol.unrefined_moment_dist - unrefined_moment_coeff_dist = solver.sol.unrefined_moment_coeff_dist - cl_unrefined_array = solver.sol.cl_unrefined_array - cd_unrefined_array = solver.sol.cd_unrefined_array - cm_unrefined_array = solver.sol.cm_unrefined_array - alpha_unrefined_array = solver.sol.alpha_unrefined_array - x_airf_unrefined_array = solver.sol.x_airf_unrefined_array - y_airf_unrefined_array = solver.sol.y_airf_unrefined_array - z_airf_unrefined_array = solver.sol.z_airf_unrefined_array - va_unrefined_array = solver.sol.va_unrefined_array - chord_unrefined_array = solver.sol.chord_unrefined_array - width_unrefined_array = solver.sol.width_unrefined_array + if length(solver.sol.moment_unrefined_dist) > 0 + moment_unrefined_dist = solver.sol.moment_unrefined_dist + cl_unrefined_dist = solver.sol.cl_unrefined_dist + cd_unrefined_dist = solver.sol.cd_unrefined_dist + cm_unrefined_dist = solver.sol.cm_unrefined_dist + alpha_unrefined_dist = solver.sol.alpha_unrefined_dist + x_airf_unrefined_dist = solver.sol.x_airf_unrefined_dist + y_airf_unrefined_dist = solver.sol.y_airf_unrefined_dist + z_airf_unrefined_dist = solver.sol.z_airf_unrefined_dist + va_unrefined_dist = solver.sol.va_unrefined_dist + chord_unrefined_dist = solver.sol.chord_unrefined_dist + width_unrefined_dist = solver.sol.width_unrefined_dist # Zero all unrefined arrays - unrefined_moment_dist .= 0.0 - unrefined_moment_coeff_dist .= 0.0 - cl_unrefined_array .= 0.0 - cd_unrefined_array .= 0.0 - cm_unrefined_array .= 0.0 - alpha_unrefined_array .= 0.0 - for i in eachindex(x_airf_unrefined_array) - x_airf_unrefined_array[i] .= 0.0 - y_airf_unrefined_array[i] .= 0.0 - z_airf_unrefined_array[i] .= 0.0 - va_unrefined_array[i] .= 0.0 + moment_unrefined_dist .= 0.0 + cl_unrefined_dist .= 0.0 + cd_unrefined_dist .= 0.0 + cm_unrefined_dist .= 0.0 + alpha_unrefined_dist .= 0.0 + for i in eachindex(x_airf_unrefined_dist) + x_airf_unrefined_dist[i] .= 0.0 + y_airf_unrefined_dist[i] .= 0.0 + z_airf_unrefined_dist[i] .= 0.0 + va_unrefined_dist[i] .= 0.0 end - chord_unrefined_array .= 0.0 - width_unrefined_array .= 0.0 + chord_unrefined_dist .= 0.0 + width_unrefined_dist .= 0.0 panel_idx = 1 unrefined_idx = 1 @@ -353,20 +353,19 @@ function solve!(solver::Solver, body_aero::BodyAerodynamics, gamma_distribution= target_unrefined_idx = unrefined_idx + original_section_idx - 1 # Accumulate coefficients and moments - unrefined_moment_dist[target_unrefined_idx] += moment_dist[panel_idx] - unrefined_moment_coeff_dist[target_unrefined_idx] += moment_coeff_dist[panel_idx] - cl_unrefined_array[target_unrefined_idx] += solver.sol.cl_array[panel_idx] - cd_unrefined_array[target_unrefined_idx] += solver.sol.cd_array[panel_idx] - cm_unrefined_array[target_unrefined_idx] += solver.sol.cm_array[panel_idx] - alpha_unrefined_array[target_unrefined_idx] += solver.sol.alpha_array[panel_idx] + moment_unrefined_dist[target_unrefined_idx] += moment_dist[panel_idx] + cl_unrefined_dist[target_unrefined_idx] += solver.sol.cl_dist[panel_idx] + cd_unrefined_dist[target_unrefined_idx] += solver.sol.cd_dist[panel_idx] + cm_unrefined_dist[target_unrefined_idx] += solver.sol.cm_dist[panel_idx] + alpha_unrefined_dist[target_unrefined_idx] += solver.sol.alpha_dist[panel_idx] # Accumulate geometry - x_airf_unrefined_array[target_unrefined_idx] .+= panel.x_airf - y_airf_unrefined_array[target_unrefined_idx] .+= panel.y_airf - z_airf_unrefined_array[target_unrefined_idx] .+= panel.z_airf - va_unrefined_array[target_unrefined_idx] .+= panel.va - chord_unrefined_array[target_unrefined_idx] += panel.chord - width_unrefined_array[target_unrefined_idx] += panel.width + x_airf_unrefined_dist[target_unrefined_idx] .+= panel.x_airf + y_airf_unrefined_dist[target_unrefined_idx] .+= panel.y_airf + z_airf_unrefined_dist[target_unrefined_idx] .+= panel.z_airf + va_unrefined_dist[target_unrefined_idx] .+= panel.va + chord_unrefined_dist[target_unrefined_idx] += panel.chord + width_unrefined_dist[target_unrefined_idx] += panel.width unrefined_section_counts[original_section_idx] += 1 panel_idx += 1 @@ -377,16 +376,17 @@ function solve!(solver::Solver, body_aero::BodyAerodynamics, gamma_distribution= target_unrefined_idx = unrefined_idx + i - 1 if unrefined_section_counts[i] > 0 count = unrefined_section_counts[i] - cl_unrefined_array[target_unrefined_idx] /= count - cd_unrefined_array[target_unrefined_idx] /= count - cm_unrefined_array[target_unrefined_idx] /= count - alpha_unrefined_array[target_unrefined_idx] /= count - x_airf_unrefined_array[target_unrefined_idx] ./= count - y_airf_unrefined_array[target_unrefined_idx] ./= count - z_airf_unrefined_array[target_unrefined_idx] ./= count - va_unrefined_array[target_unrefined_idx] ./= count - chord_unrefined_array[target_unrefined_idx] /= count - width_unrefined_array[target_unrefined_idx] /= count + moment_unrefined_dist[target_unrefined_idx] /= count + cl_unrefined_dist[target_unrefined_idx] /= count + cd_unrefined_dist[target_unrefined_idx] /= count + cm_unrefined_dist[target_unrefined_idx] /= count + alpha_unrefined_dist[target_unrefined_idx] /= count + x_airf_unrefined_dist[target_unrefined_idx] ./= count + y_airf_unrefined_dist[target_unrefined_idx] ./= count + z_airf_unrefined_dist[target_unrefined_idx] ./= count + va_unrefined_dist[target_unrefined_idx] ./= count + chord_unrefined_dist[target_unrefined_idx] /= count + width_unrefined_dist[target_unrefined_idx] /= count end end unrefined_idx += wing.n_unrefined_sections @@ -453,15 +453,15 @@ function solve(solver::Solver, body_aero::BodyAerodynamics, gamma_distribution=n solver.aerodynamic_model_type, solver.core_radius_fraction, solver.mu, - solver.lr.alpha_array, - solver.lr.v_a_array, - solver.sol._chord_array, - solver.sol._x_airf_array, - solver.sol._y_airf_array, - solver.sol._z_airf_array, - solver.sol._va_array, - solver.br.va_norm_array, - solver.br.va_unit_array, + solver.lr.alpha_dist, + solver.lr.v_a_dist, + solver.sol._chord_dist, + solver.sol._x_airf_dist, + solver.sol._y_airf_dist, + solver.sol._z_airf_dist, + solver.sol._va_dist, + solver.br.va_norm_dist, + solver.br.va_unit_dist, body_aero.panels, solver.is_only_f_and_gamma_output; correct_aoa=solver.correct_aoa @@ -469,9 +469,9 @@ function solve(solver::Solver, body_aero::BodyAerodynamics, gamma_distribution=n return results end -@inline @inbounds function calc_norm_array!(va_norm_array, va_array) +@inline @inbounds function calc_norm_array!(va_norm_dist, va_array) for i in 1:size(va_array, 1) - va_norm_array[i] = norm(MVec3(view(va_array, i, :))) + va_norm_dist[i] = norm(MVec3(view(va_array, i, :))) end end @@ -487,31 +487,31 @@ function solve_base!(solver::Solver, body_aero::BodyAerodynamics, gamma_distribu relaxation_factor = solver.relaxation_factor # Clear arrays - solver.sol._x_airf_array .= 0 - solver.sol._y_airf_array .= 0 - solver.sol._z_airf_array .= 0 - solver.sol._va_array .= 0 - solver.sol._chord_array .= 0 + solver.sol._x_airf_dist .= 0 + solver.sol._y_airf_dist .= 0 + solver.sol._z_airf_dist .= 0 + solver.sol._va_dist .= 0 + solver.sol._chord_dist .= 0 # Fill arrays from panels for (i, panel) in enumerate(panels) - solver.sol._x_airf_array[i, :] .= panel.x_airf - solver.sol._y_airf_array[i, :] .= panel.y_airf - solver.sol._z_airf_array[i, :] .= panel.z_airf - solver.sol._va_array[i, :] .= panel.va - solver.sol._chord_array[i] = panel.chord + solver.sol._x_airf_dist[i, :] .= panel.x_airf + solver.sol._y_airf_dist[i, :] .= panel.y_airf + solver.sol._z_airf_dist[i, :] .= panel.z_airf + solver.sol._va_dist[i, :] .= panel.va + solver.sol._chord_dist[i] = panel.chord end # Calculate unit vectors - calc_norm_array!(solver.br.va_norm_array, solver.sol._va_array) - solver.br.va_unit_array .= solver.sol._va_array ./ solver.br.va_norm_array + calc_norm_array!(solver.br.va_norm_dist, solver.sol._va_dist) + solver.br.va_unit_dist .= solver.sol._va_dist ./ solver.br.va_norm_dist # Calculate AIC matrices - calculate_AIC_matrices!(body_aero, solver.aerodynamic_model_type, solver.core_radius_fraction, solver.br.va_norm_array, - solver.br.va_unit_array) + calculate_AIC_matrices!(body_aero, solver.aerodynamic_model_type, solver.core_radius_fraction, solver.br.va_norm_dist, + solver.br.va_unit_dist) # Initialize gamma distribution - gamma_initial = solver.cache_base[1][solver.sol._chord_array] + gamma_initial = solver.cache_base[1][solver.sol._chord_dist] if isnothing(gamma_distribution) if solver.type_initial_gamma_distribution == ELLIPTIC calculate_circulation_distribution_elliptical_wing(gamma_initial, body_aero) @@ -552,24 +552,24 @@ function gamma_loop!( relaxation_factor::Float64; log::Bool = true ) - va_array = solver.sol._va_array - chord_array = solver.sol._chord_array - x_airf_array = solver.sol._x_airf_array - y_airf_array = solver.sol._y_airf_array - z_airf_array = solver.sol._z_airf_array + va_array = solver.sol._va_dist + chord_array = solver.sol._chord_dist + x_airf_array = solver.sol._x_airf_dist + y_airf_array = solver.sol._y_airf_dist + z_airf_array = solver.sol._z_airf_dist solver.lr.converged = false n_panels = length(body_aero.panels) - solver.lr.alpha_array .= body_aero.alpha_array - solver.lr.v_a_array .= body_aero.v_a_array + solver.lr.alpha_dist .= body_aero.alpha_dist + solver.lr.v_a_dist .= body_aero.v_a_dist - va_magw_array = solver.cache[1][solver.lr.v_a_array] + va_magw_array = solver.cache[1][solver.lr.v_a_dist] gamma = solver.cache[2][solver.lr.gamma_new] abs_gamma_new = solver.cache[3][solver.lr.gamma_new] induced_velocity_all = solver.cache[4][va_array] relative_velocity_array = solver.cache[5][va_array] relative_velocity_crossz = solver.cache[6][va_array] v_acrossz_array = solver.cache[7][va_array] - cl_array = solver.cache[8][solver.lr.gamma_new] + cl_dist = solver.cache[8][solver.lr.gamma_new] damp = solver.cache[9][solver.lr.gamma_new] v_normal_array = solver.cache[10][solver.lr.gamma_new] v_tangential_array = solver.cache[11][solver.lr.gamma_new] @@ -600,17 +600,17 @@ function gamma_loop!( v_normal_array[i] = view(z_airf_array, i, :) ⋅ view(relative_velocity_array, i, :) v_tangential_array[i] = view(x_airf_array, i, :) ⋅ view(relative_velocity_array, i, :) end - solver.lr.alpha_array .= atan.(v_normal_array, v_tangential_array) + solver.lr.alpha_dist .= atan.(v_normal_array, v_tangential_array) for i in 1:n_panels - @views solver.lr.v_a_array[i] = norm(relative_velocity_crossz[i, :]) + @views solver.lr.v_a_dist[i] = norm(relative_velocity_crossz[i, :]) @views va_magw_array[i] = norm(v_acrossz_array[i, :]) end - for (i, (panel, alpha)) in enumerate(zip(panels, solver.lr.alpha_array)) - cl_array[i] = calculate_cl(panel, alpha) + for (i, (panel, alpha)) in enumerate(zip(panels, solver.lr.alpha_dist)) + cl_dist[i] = calculate_cl(panel, alpha) end - gamma_new .= 0.5 .* solver.lr.v_a_array.^2 ./ va_magw_array .* cl_array .* chord_array + gamma_new .= 0.5 .* solver.lr.v_a_dist.^2 ./ va_magw_array .* cl_dist .* chord_array nothing end @@ -769,8 +769,8 @@ Jacobian computation. When the same angles are encountered, geometry deformation # Returns - `jac::Matrix{Float64}`: Jacobian matrix (m×n) where m = 6 + n_unrefined_sections, n = length(y) - `results::Vector{Float64}`: Output vector at operating point - - If `aero_coeffs=false`: [Fx, Fy, Fz, Mx, My, Mz, unrefined_moment_dist...] - - If `aero_coeffs=true`: [CFx, CFy, CFz, CMx, CMy, CMz, unrefined_moment_coeff_dist...] + - If `aero_coeffs=false`: [Fx, Fy, Fz, Mx, My, Mz, moment_unrefined_dist...] + - If `aero_coeffs=true`: [CFx, CFy, CFz, CMx, CMy, CMz, cm_unrefined_dist...] # Example ```julia @@ -868,16 +868,16 @@ function linearize(solver::Solver, body_aero::BodyAerodynamics, y::Vector{T}; if !aero_coeffs results[1:3] .= solver.sol.force results[4:6] .= solver.sol.moment - results[7:end] .= solver.sol.unrefined_moment_dist + results[7:end] .= solver.sol.moment_unrefined_dist else results[1:3] .= solver.sol.force_coeffs results[4:6] .= solver.sol.moment_coeffs - results[7:end] .= solver.sol.unrefined_moment_coeff_dist + results[7:end] .= solver.sol.cm_unrefined_dist end return nothing end - results = zeros(3+3+length(solver.sol.unrefined_moment_dist)) + results = zeros(3+3+length(solver.sol.moment_unrefined_dist)) jac = zeros(length(results), length(y)) backend = AutoFiniteDiff(absstep=1e2solver.atol, relstep=1e2solver.rtol) prep = prepare_jacobian(calc_results!, results, backend, y) From a97157468d0c3747c3362f1a119ac1de46cf5783 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sat, 6 Dec 2025 16:28:39 +0100 Subject: [PATCH 35/86] Update the deform functions to make more sense --- src/body_aerodynamics.jl | 5 +- src/obj_geometry.jl | 2 +- src/wing_geometry.jl | 169 +++++++++++++++++++++++++++------------ 3 files changed, 121 insertions(+), 55 deletions(-) diff --git a/src/body_aerodynamics.jl b/src/body_aerodynamics.jl index 539c95f9..1ca1506f 100644 --- a/src/body_aerodynamics.jl +++ b/src/body_aerodynamics.jl @@ -157,9 +157,8 @@ function reinit!(body_aero::BodyAerodynamics; # Create panels for i in 1:wing.n_panels if !isnothing(wing.delta_dist) && length(wing.delta_dist) > 0 - # Map refined panel to unrefined section to get delta value - unrefined_idx = wing.refined_panel_mapping[i] - delta = wing.delta_dist[unrefined_idx] + # Panel i gets its delta directly from delta_dist[i] + delta = wing.delta_dist[i] else delta = 0.0 end diff --git a/src/obj_geometry.jl b/src/obj_geometry.jl index 2a654893..c77e122e 100644 --- a/src/obj_geometry.jl +++ b/src/obj_geometry.jl @@ -523,7 +523,7 @@ function ObjWing( wing = Wing(n_panels, Int16(n_unrefined_sections), spanwise_distribution, panel_props, MVec3(spanwise_direction), sections, refined_sections, remove_nan, Int16[], - Section[], zeros(n_unrefined_sections), zeros(n_unrefined_sections), + Section[], zeros(n_panels), zeros(n_panels), mass, gamma_tip, inertia_tensor, T_cad_body, R_cad_body, radius, le_interp, te_interp, area_interp, cache) diff --git a/src/wing_geometry.jl b/src/wing_geometry.jl index 857f5fe5..2345bd46 100644 --- a/src/wing_geometry.jl +++ b/src/wing_geometry.jl @@ -236,8 +236,8 @@ mutable struct Wing <: AbstractWing # Deformation fields non_deformed_sections::Vector{Section} - theta_dist::Vector{Float64} # Length: n_unrefined_sections (section twist angles) - delta_dist::Vector{Float64} # Length: n_unrefined_sections (section TE deflection angles) + theta_dist::Vector{Float64} # Length: n_panels (panel twist angles) + delta_dist::Vector{Float64} # Length: n_panels (panel TE deflection angles) # Physical properties (OBJ-based wings) mass::Float64 @@ -307,7 +307,7 @@ function Wing(n_panels::Int; # Grouping Int16[], # Deformation fields - Section[], zeros(max(0, n_unrefined_sections_value)), zeros(max(0, n_unrefined_sections_value)), + Section[], zeros(max(0, n_panels)), zeros(max(0, n_panels)), # Physical properties (defaults for non-OBJ wings) 0.0, 0.0, zeros(0, 0), zeros(MVec3), Matrix{Float64}(I, 3, 3), 0.0, nothing, nothing, nothing, @@ -372,7 +372,8 @@ if both angle inputs are nothing. # Returns - `nothing` (modifies wing in-place) """ -function unrefined_deform!(wing::Wing, theta_angles=nothing, delta_angles=nothing; smooth=false) +function unrefined_deform!(wing::Wing, theta_angles=nothing, delta_angles=nothing; + smooth=false, smooth_window=nothing) # Check if deformation is supported can_deform = !isempty(wing.non_deformed_sections) @@ -390,91 +391,156 @@ function unrefined_deform!(wing::Wing, theta_angles=nothing, delta_angles=nothin !isnothing(delta_angles) && length(delta_angles) != wing.n_unrefined_sections && throw(ArgumentError("delta_angles must have length n_unrefined_sections = $(wing.n_unrefined_sections), got $(length(delta_angles))")) - # Copy angles to theta_dist and delta_dist - !isnothing(theta_angles) && (wing.theta_dist .= theta_angles) - !isnothing(delta_angles) && (wing.delta_dist .= delta_angles) + # Map unrefined sections → panels → sections (no smoothing yet) + if !isnothing(theta_angles) + map_unrefined_to_sections!(wing.theta_dist, theta_angles, wing.refined_panel_mapping, wing.n_panels) + end + if !isnothing(delta_angles) + map_unrefined_to_sections!(wing.delta_dist, delta_angles, wing.refined_panel_mapping, wing.n_panels) + end - # Apply 3-point moving average smoothing if requested - if smooth && wing.n_unrefined_sections > 2 - if !isnothing(theta_angles) - for i in 2:(wing.n_unrefined_sections-1) - wing.theta_dist[i] = (wing.theta_dist[i-1] + wing.theta_dist[i] + wing.theta_dist[i+1]) / 3.0 - end - end - if !isnothing(delta_angles) - for i in 2:(wing.n_unrefined_sections-1) - wing.delta_dist[i] = (wing.delta_dist[i-1] + wing.delta_dist[i] + wing.delta_dist[i+1]) / 3.0 - end - end + # Apply deformation with optional smoothing + deform!(wing, smooth=smooth, smooth_window=smooth_window) + return nothing +end + +""" + map_unrefined_to_sections!(panel_dist, unrefined_angles, panel_mapping, n_panels) + +Map angles from unrefined sections to panels. +Steps: unrefined[1:n_unrefined] → panels[1:n_panels] + +# Arguments +- `panel_dist::Vector{Float64}`: Output panel angles (length n_panels) +- `unrefined_angles::Vector{Float64}`: Input unrefined section angles +- `panel_mapping::Vector{Int16}`: Maps panel index to unrefined section index +- `n_panels::Int`: Number of panels +""" +function map_unrefined_to_sections!(panel_dist, + unrefined_angles, + panel_mapping, + n_panels) + # Map unrefined sections to panels + for i in 1:n_panels + unrefined_idx = panel_mapping[i] + panel_dist[i] = unrefined_angles[unrefined_idx] end - deform!(wing) return nothing end """ - deform!(wing::Wing, theta_dist::AbstractVector, delta_dist::AbstractVector) + smooth_distribution!(dist, window_size) -Deform wing by applying theta and delta distributions directly to unrefined sections. +Apply moving average smoothing to a distribution in-place. +Uses a centered window of size `window_size` (must be odd). + +# Arguments +- `dist::Vector{Float64}`: Distribution to smooth (modified in-place) +- `window_size::Int`: Size of smoothing window (must be odd) +""" +function smooth_distribution!(dist::Vector{Float64}, window_size::Int) + n = length(dist) + window_size <= 1 && return nothing + n <= window_size && return nothing + + # Create temporary copy + dist_copy = copy(dist) + half_window = div(window_size, 2) + + # Apply moving average + for i in 1:n + start_idx = max(1, i - half_window) + end_idx = min(n, i + half_window) + dist[i] = sum(dist_copy[start_idx:end_idx]) / (end_idx - start_idx + 1) + end + + return nothing +end + +""" + deform!(wing::Wing, theta_dist::AbstractVector, delta_dist::AbstractVector; + smooth=false, smooth_window=nothing) + +Deform wing by applying theta and delta distributions at the panel level. # Arguments - `wing::Wing`: Wing to deform (must support deformation) -- `theta_dist::AbstractVector`: Twist angle in radians for each unrefined section (length = n_unrefined_sections) -- `delta_dist::AbstractVector`: Trailing edge deflection for each unrefined section (length = n_unrefined_sections) +- `theta_dist::AbstractVector`: Twist angles for each panel (length = n_panels) +- `delta_dist::AbstractVector`: TE deflections for each panel (length = n_panels) +- `smooth::Bool`: Whether to apply smoothing (default: false) +- `smooth_window::Union{Nothing, Int}`: Smoothing window size (default: auto-calculated) # Effects -Updates wing.unrefined_sections with deformed geometry based on wing.non_deformed_sections +Updates wing.refined_sections with deformed geometry based on wing.non_deformed_sections """ -function deform!(wing::Wing, theta_dist::AbstractVector, delta_dist::AbstractVector) +function deform!(wing::Wing, theta_dist::AbstractVector, delta_dist::AbstractVector; + smooth=false, smooth_window=nothing) !isempty(wing.non_deformed_sections) || throw(ArgumentError("Wing does not support deformation")) - !(length(theta_dist) == wing.n_unrefined_sections) && throw(ArgumentError("theta_dist must have length $(wing.n_unrefined_sections), got $(length(theta_dist))")) - !(length(delta_dist) == wing.n_unrefined_sections) && throw(ArgumentError("delta_dist must have length $(wing.n_unrefined_sections), got $(length(delta_dist))")) + + expected_len = wing.n_panels + !(length(theta_dist) == expected_len) && throw(ArgumentError("theta_dist must have length $(expected_len), got $(length(theta_dist))")) + !(length(delta_dist) == expected_len) && throw(ArgumentError("delta_dist must have length $(expected_len), got $(length(delta_dist))")) + wing.theta_dist .= theta_dist wing.delta_dist .= delta_dist - deform!(wing) + deform!(wing, smooth=smooth, smooth_window=smooth_window) end """ - deform!(wing::Wing) + deform!(wing::Wing; smooth=false, smooth_window=nothing) Apply stored theta_dist and delta_dist to deform the wing geometry. - -Deformation works by: -1. Applying theta/delta angles to unrefined sections (wing.unrefined_sections) -2. Using refined_panel_mapping to determine which unrefined section each refined section came from -3. Applying the corresponding angle to each refined section +Converts panel angles (n_panels) to section angles (n_panels+1) by averaging adjacent panels. # Arguments - `wing::Wing`: Wing to deform (must have non_deformed_sections) +- `smooth::Bool`: Whether to apply smoothing to theta_dist and delta_dist (default: false) +- `smooth_window::Union{Nothing, Int}`: Smoothing window size (default: auto-calculated) # Effects Updates wing.refined_sections based on wing.non_deformed_sections and stored distributions """ -function deform!(wing::Wing) +function deform!(wing::Wing; smooth=false, smooth_window=nothing) !isempty(wing.non_deformed_sections) || return nothing + # Apply smoothing if requested + if smooth + # Default window size based on refinement ratio + if isnothing(smooth_window) + smooth_window = max(3, round(Int, wing.n_panels / wing.n_unrefined_sections)) + end + + # Ensure window is odd for symmetric averaging + if smooth_window % 2 == 0 + smooth_window += 1 + end + + # Apply moving average to theta_dist and delta_dist (panel-level) + smooth_distribution!(wing.theta_dist, smooth_window) + smooth_distribution!(wing.delta_dist, smooth_window) + end + local_y = zeros(MVec3) chord = zeros(MVec3) normal = zeros(MVec3) # Process all refined sections (n_panels + 1) - # Each refined section gets the angle from its corresponding unrefined section + # Convert panel angles to section angles by averaging for i in 1:(wing.n_panels + 1) - # Determine which unrefined section this refined section belongs to + # Determine theta for this section by averaging adjacent panels if i == 1 - # First section: use first unrefined section - unrefined_idx = 1 + # First section: use panel 1 angle + theta = wing.theta_dist[1] elseif i == wing.n_panels + 1 - # Last section: use last unrefined section - unrefined_idx = wing.n_unrefined_sections + # Last section: use last panel angle + theta = wing.theta_dist[wing.n_panels] else - # Middle sections: use the mapping from the panel to the left - unrefined_idx = wing.refined_panel_mapping[i-1] + # Middle sections: average of panels (i-1) and i + theta = (wing.theta_dist[i-1] + wing.theta_dist[i]) / 2.0 end - theta = wing.theta_dist[unrefined_idx] - section = wing.non_deformed_sections[i] # Compute local coordinate system @@ -693,13 +759,14 @@ function refine_aerodynamic_mesh!(wing::AbstractWing; recompute_mapping=true, so # Update n_unrefined_sections based on actual sections wing.n_unrefined_sections = Int16(length(wing.unrefined_sections)) - # Resize theta_dist and delta_dist to match n_unrefined_sections - if length(wing.theta_dist) != wing.n_unrefined_sections - resize!(wing.theta_dist, wing.n_unrefined_sections) + # Resize theta_dist and delta_dist to match n_panels + target_size = wing.n_panels + if length(wing.theta_dist) != target_size + resize!(wing.theta_dist, target_size) fill!(wing.theta_dist, 0.0) end - if length(wing.delta_dist) != wing.n_unrefined_sections - resize!(wing.delta_dist, wing.n_unrefined_sections) + if length(wing.delta_dist) != target_size + resize!(wing.delta_dist, target_size) fill!(wing.delta_dist, 0.0) end From 4a6a37170b590461e3a3f98b06aa706d9b296b60 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sat, 6 Dec 2025 16:29:19 +0100 Subject: [PATCH 36/86] Update tests for recent changes --- test/bench.jl | 43 +++++++--- .../test_body_aerodynamics.jl | 3 - test/body_aerodynamics/test_results.jl | 12 +-- test/ram_geometry/test_kite_geometry.jl | 4 +- test/runtests.jl | 4 +- test/wing_geometry/test_wing_geometry.jl | 60 ++++++------- .../test_yaml_wing_deformation.jl | 85 ++++++++++++++++--- 7 files changed, 141 insertions(+), 70 deletions(-) diff --git a/test/bench.jl b/test/bench.jl index 88172d69..b5d1ba27 100644 --- a/test/bench.jl +++ b/test/bench.jl @@ -14,6 +14,9 @@ using VortexStepMethod: calculate_AIC_matrices!, gamma_loop!, calculate_results, using Test using LinearAlgebra +# Check Julia version for known allocation issues +const IS_JULIA_1_12_OR_NEWER = VERSION >= v"1.12" + @testset "Function Allocation Tests" begin # Define wing parameters n_panels = 20 # Number of panels @@ -85,7 +88,11 @@ using LinearAlgebra for frac in core_radius_fractions @testset "Model $model Core Radius Fraction $frac" begin result = @benchmark calculate_AIC_matrices!($body_aero, $model, $frac, $va_norm_array, $va_unit_array) samples=1 evals=1 - @test result.allocs ≤ 30 + if IS_JULIA_1_12_OR_NEWER + @test_broken result.allocs ≤ 30 + else + @test result.allocs ≤ 30 + end @info "Model: $(model) \t Core radius fraction: $(frac) \t Allocations: $(result.allocs) \t Memory: $(result.memory)" end end @@ -134,11 +141,11 @@ using LinearAlgebra solver = Solver(body_aero; aerodynamic_model_type=model ) - solver.sol._va_array .= va_array - solver.sol._chord_array .= chord_array - solver.sol._x_airf_array .= x_airf_array - solver.sol._y_airf_array .= y_airf_array - solver.sol._z_airf_array .= z_airf_array + solver.sol._va_dist .= va_array + solver.sol._chord_dist .= chord_array + solver.sol._x_airf_dist .= x_airf_array + solver.sol._y_airf_dist .= y_airf_array + solver.sol._z_airf_dist .= z_airf_array result = @benchmark gamma_loop!( $solver, $body_aero, @@ -203,17 +210,33 @@ using LinearAlgebra @testset "Allocation Tests for solve() and solve!()" begin result = @benchmark solve_base!($solver, $body_aero, nothing) samples=1 evals=1 # 51 allocations - @test result.allocs <= 55 + if IS_JULIA_1_12_OR_NEWER + @test_broken result.allocs <= 55 + else + @test result.allocs <= 55 + end # time Python: 32.0 ms Ryzen 7950x # time Julia: 0.45 ms Ryzen 7950x result = @benchmark sol = solve!($solver, $body_aero, nothing) samples=1 evals=1 # 85 allocations - @test result.allocs <= 89 + if IS_JULIA_1_12_OR_NEWER + @test_broken result.allocs <= 89 + else + @test result.allocs <= 89 + end # Step 5: Solve using both methods result = @benchmark solve_base!($nonlin_solver, $body_aero, nothing) samples=1 evals=1 # 51 allocations - @test result.allocs <= 55 + if IS_JULIA_1_12_OR_NEWER + @test_broken result.allocs <= 55 + else + @test result.allocs <= 55 + end result = @benchmark sol = solve!($nonlin_solver, $body_aero, nothing) samples=1 evals=1 # 85 allocations - @test result.allocs <= 89 + if IS_JULIA_1_12_OR_NEWER + @test_broken result.allocs <= 89 + else + @test result.allocs <= 89 + end end end diff --git a/test/body_aerodynamics/test_body_aerodynamics.jl b/test/body_aerodynamics/test_body_aerodynamics.jl index 239e5113..6e61857c 100644 --- a/test/body_aerodynamics/test_body_aerodynamics.jl +++ b/test/body_aerodynamics/test_body_aerodynamics.jl @@ -351,9 +351,6 @@ end @test loop_sol.solver_status == FEASIBLE - @test sum(loop_sol.moment_dist) ≈ sum(loop_sol.unrefined_moment_dist) - @test sum(nonlin_sol.moment_dist) ≈ sum(nonlin_sol.unrefined_moment_dist) - end # Calculate forces using uncorrected alpha diff --git a/test/body_aerodynamics/test_results.jl b/test/body_aerodynamics/test_results.jl index 80be8585..5378bedf 100644 --- a/test/body_aerodynamics/test_results.jl +++ b/test/body_aerodynamics/test_results.jl @@ -85,8 +85,8 @@ end # Verify that linearization results match nonlinear results at operating point baseline_res = VortexStepMethod.solve!(solver, body_aero; log=false) - baseline_res = [solver.sol.force; solver.sol.moment; solver.sol.unrefined_moment_dist] - coeff_baseline_res = [solver.sol.force_coeffs; solver.sol.moment_coeffs; solver.sol.unrefined_moment_coeff_dist] + baseline_res = [solver.sol.force; solver.sol.moment; solver.sol.moment_unrefined_dist] + coeff_baseline_res = [solver.sol.force_coeffs; solver.sol.moment_coeffs; solver.sol.cm_unrefined_dist] @test baseline_res ≈ lin_res @test coeff_baseline_res ≈ coeff_lin_res @@ -142,8 +142,8 @@ end # Get nonlinear solution nonlin_res = VortexStepMethod.solve!(solver, body_aero, nothing; log=false) - nonlin_res = [solver.sol.force; solver.sol.moment; solver.sol.unrefined_moment_dist] - coeff_nonlin_res = [solver.sol.force_coeffs; solver.sol.moment_coeffs; solver.sol.unrefined_moment_coeff_dist] + nonlin_res = [solver.sol.force; solver.sol.moment; solver.sol.moment_unrefined_dist] + coeff_nonlin_res = [solver.sol.force_coeffs; solver.sol.moment_coeffs; solver.sol.cm_unrefined_dist] @test nonlin_res ≉ baseline_res @test coeff_nonlin_res ≉ baseline_res @@ -250,7 +250,7 @@ end # Get baseline results baseline_res = VortexStepMethod.solve!(solver, body_aero; log=false) - baseline_res = [solver.sol.force; solver.sol.moment; solver.sol.unrefined_moment_dist] + baseline_res = [solver.sol.force; solver.sol.moment; solver.sol.moment_unrefined_dist] # Should match the linearization result @test baseline_res ≈ lin_res_combo @@ -277,7 +277,7 @@ end # Get nonlinear solution with perturbation nonlin_res = VortexStepMethod.solve!(solver, body_aero; log=false) - nonlin_res = [solver.sol.force; solver.sol.moment; solver.sol.unrefined_moment_dist] + nonlin_res = [solver.sol.force; solver.sol.moment; solver.sol.moment_unrefined_dist] # Compute linearized prediction using our specialized Jacobian lin_prediction = lin_res_combo + jac_combo * perturbation diff --git a/test/ram_geometry/test_kite_geometry.jl b/test/ram_geometry/test_kite_geometry.jl index d76cc533..3058af89 100644 --- a/test/ram_geometry/test_kite_geometry.jl +++ b/test/ram_geometry/test_kite_geometry.jl @@ -195,8 +195,8 @@ using Serialization original_te_point = copy(body_aero.panels[i].TE_point_1) # Apply deformation with non-zero angles - theta_dist = fill(deg2rad(30.0), wing.n_unrefined_sections) # 30 degrees twist for all sections - delta_dist = fill(deg2rad(5.0), wing.n_unrefined_sections) # 5 degrees trailing edge deflection for all sections + theta_dist = fill(deg2rad(30.0), wing.n_panels) # 30 degrees twist for all panels + delta_dist = fill(deg2rad(5.0), wing.n_panels) # 5 degrees TE deflection for all panels VortexStepMethod.deform!(wing, theta_dist, delta_dist) VortexStepMethod.reinit!(body_aero) diff --git a/test/runtests.jl b/test/runtests.jl index 7a2abdd5..d0b770d4 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -16,7 +16,7 @@ end function should_run_test(test_path::String) isempty(test_patterns) && return true for pattern in test_patterns - # Match directory (e.g., "solver") or specific file (e.g., "test_group_coefficients") + # Match directory (e.g., "solver") or specific file (e.g., "test_unrefined_dist") if occursin(pattern, test_path) return true end @@ -45,7 +45,7 @@ end::Bool should_run_test("ram_geometry/test_kite_geometry.jl") && include("ram_geometry/test_kite_geometry.jl") should_run_test("settings/test_settings.jl") && include("settings/test_settings.jl") should_run_test("solver/test_solver.jl") && include("solver/test_solver.jl") - should_run_test("solver/test_group_coefficients.jl") && include("solver/test_group_coefficients.jl") + should_run_test("solver/test_unrefined_dist.jl") && include("solver/test_unrefined_dist.jl") should_run_test("VortexStepMethod/test_VortexStepMethod.jl") && include("VortexStepMethod/test_VortexStepMethod.jl") should_run_test("wake/test_wake.jl") && include("wake/test_wake.jl") should_run_test("wing_geometry/test_wing_geometry.jl") && include("wing_geometry/test_wing_geometry.jl") diff --git a/test/wing_geometry/test_wing_geometry.jl b/test/wing_geometry/test_wing_geometry.jl index 5e458c2a..8c4ba69c 100644 --- a/test/wing_geometry/test_wing_geometry.jl +++ b/test/wing_geometry/test_wing_geometry.jl @@ -341,7 +341,7 @@ end span = 10.0 wing = Wing(n_panels; spanwise_distribution=LINEAR) - # 3 sections = 2 unrefined panels + # 3 sections add_section!(wing, [0.0, span/2, 0.0], [1.0, span/2, 0.0], INVISCID) add_section!(wing, [0.0, 0.0, 0.0], [1.0, 0.0, 0.0], INVISCID) add_section!(wing, [0.0, -span/2, 0.0], [1.0, -span/2, 0.0], INVISCID) @@ -350,8 +350,8 @@ end @test length(wing.refined_panel_mapping) == n_panels - # Manually verify each refined panel is mapped to its closest unrefined panel - n_unrefined_panels = length(wing.unrefined_sections) - 1 + # Manually verify each refined panel is mapped to its closest unrefined section + n_unrefined_sections = length(wing.unrefined_sections) for refined_panel_idx in 1:n_panels # Calculate refined panel center le_mid = (wing.refined_sections[refined_panel_idx].LE_point + @@ -360,20 +360,18 @@ end wing.refined_sections[refined_panel_idx+1].TE_point) / 2 refined_center = (le_mid + te_mid) / 2 - # Find closest unrefined panel manually + # Find closest unrefined section manually min_dist = Inf closest_idx = 1 - for unrefined_panel_idx in 1:n_unrefined_panels - le_mid_unref = (wing.unrefined_sections[unrefined_panel_idx].LE_point + - wing.unrefined_sections[unrefined_panel_idx+1].LE_point) / 2 - te_mid_unref = (wing.unrefined_sections[unrefined_panel_idx].TE_point + - wing.unrefined_sections[unrefined_panel_idx+1].TE_point) / 2 - unrefined_center = (le_mid_unref + te_mid_unref) / 2 + for unrefined_section_idx in 1:n_unrefined_sections + le_point = wing.unrefined_sections[unrefined_section_idx].LE_point + te_point = wing.unrefined_sections[unrefined_section_idx].TE_point + unrefined_center = (le_point + te_point) / 2 dist = norm(refined_center - unrefined_center) if dist < min_dist min_dist = dist - closest_idx = unrefined_panel_idx + closest_idx = unrefined_section_idx end end @@ -387,7 +385,7 @@ end span = 20.0 wing = Wing(n_panels; spanwise_distribution=COSINE) - # 4 sections = 3 unrefined panels + # 4 sections add_section!(wing, [0.0, span/2, 0.0], [1.0, span/2, 0.0], INVISCID) add_section!(wing, [0.0, span/6, 0.0], [1.0, span/6, 0.0], INVISCID) add_section!(wing, [0.0, -span/6, 0.0], [1.0, -span/6, 0.0], INVISCID) @@ -397,8 +395,8 @@ end @test length(wing.refined_panel_mapping) == n_panels - # Verify each panel is mapped to its closest unrefined panel - n_unrefined_panels = length(wing.unrefined_sections) - 1 + # Verify each panel is mapped to its closest unrefined section + n_unrefined_sections = length(wing.unrefined_sections) for refined_panel_idx in 1:n_panels # Calculate refined panel center le_mid = (wing.refined_sections[refined_panel_idx].LE_point + @@ -407,20 +405,18 @@ end wing.refined_sections[refined_panel_idx+1].TE_point) / 2 refined_center = (le_mid + te_mid) / 2 - # Find closest unrefined panel manually + # Find closest unrefined section manually min_dist = Inf closest_idx = 1 - for unrefined_panel_idx in 1:n_unrefined_panels - le_mid_unref = (wing.unrefined_sections[unrefined_panel_idx].LE_point + - wing.unrefined_sections[unrefined_panel_idx+1].LE_point) / 2 - te_mid_unref = (wing.unrefined_sections[unrefined_panel_idx].TE_point + - wing.unrefined_sections[unrefined_panel_idx+1].TE_point) / 2 - unrefined_center = (le_mid_unref + te_mid_unref) / 2 + for unrefined_section_idx in 1:n_unrefined_sections + le_point = wing.unrefined_sections[unrefined_section_idx].LE_point + te_point = wing.unrefined_sections[unrefined_section_idx].TE_point + unrefined_center = (le_point + te_point) / 2 dist = norm(refined_center - unrefined_center) if dist < min_dist min_dist = dist - closest_idx = unrefined_panel_idx + closest_idx = unrefined_section_idx end end @@ -433,7 +429,7 @@ end n_panels = 12 wing = Wing(n_panels; spanwise_distribution=SPLIT_PROVIDED) - # 4 sections = 3 unrefined panels + # 4 sections add_section!(wing, [0.0, 6.0, 0.0], [1.0, 6.0, 0.0], INVISCID) add_section!(wing, [0.0, 2.0, 0.0], [1.0, 2.0, 0.0], INVISCID) add_section!(wing, [0.0, -2.0, 0.0], [1.0, -2.0, 0.0], INVISCID) @@ -443,8 +439,8 @@ end @test length(wing.refined_panel_mapping) == n_panels - # Verify each panel is mapped to its closest unrefined panel - n_unrefined_panels = length(wing.unrefined_sections) - 1 + # Verify each panel is mapped to its closest unrefined section + n_unrefined_sections = length(wing.unrefined_sections) for refined_panel_idx in 1:n_panels # Calculate refined panel center le_mid = (wing.refined_sections[refined_panel_idx].LE_point + @@ -453,20 +449,18 @@ end wing.refined_sections[refined_panel_idx+1].TE_point) / 2 refined_center = (le_mid + te_mid) / 2 - # Find closest unrefined panel manually + # Find closest unrefined section manually min_dist = Inf closest_idx = 1 - for unrefined_panel_idx in 1:n_unrefined_panels - le_mid_unref = (wing.unrefined_sections[unrefined_panel_idx].LE_point + - wing.unrefined_sections[unrefined_panel_idx+1].LE_point) / 2 - te_mid_unref = (wing.unrefined_sections[unrefined_panel_idx].TE_point + - wing.unrefined_sections[unrefined_panel_idx+1].TE_point) / 2 - unrefined_center = (le_mid_unref + te_mid_unref) / 2 + for unrefined_section_idx in 1:n_unrefined_sections + le_point = wing.unrefined_sections[unrefined_section_idx].LE_point + te_point = wing.unrefined_sections[unrefined_section_idx].TE_point + unrefined_center = (le_point + te_point) / 2 dist = norm(refined_center - unrefined_center) if dist < min_dist min_dist = dist - closest_idx = unrefined_panel_idx + closest_idx = unrefined_section_idx end end diff --git a/test/yaml_geometry/test_yaml_wing_deformation.jl b/test/yaml_geometry/test_yaml_wing_deformation.jl index 4b434de7..d483835a 100644 --- a/test/yaml_geometry/test_yaml_wing_deformation.jl +++ b/test/yaml_geometry/test_yaml_wing_deformation.jl @@ -14,9 +14,9 @@ using Test original_te_point = copy(body_aero.panels[i].TE_point_1) original_le_point = copy(body_aero.panels[i].LE_point_1) - # Apply deformation with non-zero angles - theta_dist = fill(deg2rad(30.0), wing.n_unrefined_sections) # 30 degrees twist - delta_dist = fill(deg2rad(5.0), wing.n_unrefined_sections) # 5 degrees trailing edge deflection + # Apply deformation with non-zero angles (panel-level) + theta_dist = fill(deg2rad(30.0), wing.n_panels) # 30 degrees twist per panel + delta_dist = fill(deg2rad(5.0), wing.n_panels) # 5 degrees TE deflection per panel VortexStepMethod.deform!(wing, theta_dist, delta_dist) VortexStepMethod.reinit!(body_aero; refine_mesh=false) @@ -36,8 +36,8 @@ using Test @test body_aero.panels[i].delta ≈ deg2rad(5.0) # Reset deformation with zero angles - zero_theta_dist = zeros(wing.n_unrefined_sections) - zero_delta_dist = zeros(wing.n_unrefined_sections) + zero_theta_dist = zeros(wing.n_panels) + zero_delta_dist = zeros(wing.n_panels) VortexStepMethod.deform!(wing, zero_theta_dist, zero_delta_dist) VortexStepMethod.reinit!(body_aero; refine_mesh=false) @@ -66,8 +66,8 @@ using Test )) end - # Apply spanwise-varying deformation - n = wing.n_unrefined_sections + # Apply spanwise-varying deformation (panel-level) + n = wing.n_panels theta_dist = [deg2rad(10.0 * i / n) for i in 1:n] # Linear twist distribution delta_dist = [deg2rad(-5.0 + 10.0 * i / n) for i in 1:n] # Varying deflection @@ -130,8 +130,8 @@ using Test body_aero = BodyAerodynamics([wing]) # Apply deformation - theta_dist = fill(deg2rad(15.0), wing.n_unrefined_sections) - delta_dist = fill(deg2rad(3.0), wing.n_unrefined_sections) + theta_dist = fill(deg2rad(15.0), wing.n_panels) + delta_dist = fill(deg2rad(3.0), wing.n_panels) VortexStepMethod.deform!(wing, theta_dist, delta_dist) VortexStepMethod.reinit!(body_aero; refine_mesh=false) @@ -158,13 +158,13 @@ using Test body_aero = BodyAerodynamics([wing]) # Test zero deformation - VortexStepMethod.deform!(wing, zeros(wing.n_unrefined_sections), zeros(wing.n_unrefined_sections)) + VortexStepMethod.deform!(wing, zeros(wing.n_panels), zeros(wing.n_panels)) VortexStepMethod.reinit!(body_aero; refine_mesh=false) @test all(p.delta ≈ 0.0 for p in body_aero.panels) # Test large deformation angles - theta_dist = fill(deg2rad(60.0), wing.n_unrefined_sections) - delta_dist = fill(deg2rad(30.0), wing.n_unrefined_sections) + theta_dist = fill(deg2rad(60.0), wing.n_panels) + delta_dist = fill(deg2rad(30.0), wing.n_panels) # Should not error even with large angles VortexStepMethod.deform!(wing, theta_dist, delta_dist) @@ -172,10 +172,67 @@ using Test @test all(p.delta ≈ deg2rad(30.0) for p in body_aero.panels) # Test negative angles - theta_dist = fill(deg2rad(-20.0), wing.n_unrefined_sections) - delta_dist = fill(deg2rad(-10.0), wing.n_unrefined_sections) + theta_dist = fill(deg2rad(-20.0), wing.n_panels) + delta_dist = fill(deg2rad(-10.0), wing.n_panels) VortexStepMethod.deform!(wing, theta_dist, delta_dist) VortexStepMethod.reinit!(body_aero; refine_mesh=false) @test all(p.delta ≈ deg2rad(-10.0) for p in body_aero.panels) end + + @testset "Panel to Section Angle Mapping" begin + # Test that panel angles are correctly averaged to section angles + simple_wing_file = test_data_path("yaml_geometry", "simple_wing.yaml") + wing = Wing(simple_wing_file; n_panels=4) + body_aero = BodyAerodynamics([wing]) + + # Create varying panel angles + theta_panel = [10.0, 20.0, 30.0, 40.0] # degrees per panel + delta_panel = [5.0, 10.0, 15.0, 20.0] # degrees per panel + + # Apply deformation + VortexStepMethod.deform!(wing, deg2rad.(theta_panel), deg2rad.(delta_panel)) + + # Verify section angles by checking the geometry + # Section 1: should use panel 1 angle = 10° + # Section 2: should avg panels 1,2 = (10+20)/2 = 15° + # Section 3: should avg panels 2,3 = (20+30)/2 = 25° + # Section 4: should avg panels 3,4 = (30+40)/2 = 35° + # Section 5: should use panel 4 angle = 40° + + # We can verify this by checking that delta values are correct + VortexStepMethod.reinit!(body_aero; refine_mesh=false) + + # Each panel gets its delta directly + @test body_aero.panels[1].delta ≈ deg2rad(5.0) atol=1e-6 + @test body_aero.panels[2].delta ≈ deg2rad(10.0) atol=1e-6 + @test body_aero.panels[3].delta ≈ deg2rad(15.0) atol=1e-6 + @test body_aero.panels[4].delta ≈ deg2rad(20.0) atol=1e-6 + end + + @testset "unrefined_deform! Maps to Panels" begin + # Test that unrefined_deform! correctly maps unrefined sections to panels + # Use complex_wing which has 7 unrefined sections + complex_wing_file = test_data_path("yaml_geometry", "complex_wing.yaml") + wing = Wing(complex_wing_file; n_panels=12) + body_aero = BodyAerodynamics([wing]) + + # Verify we have 7 unrefined sections + @test wing.n_unrefined_sections == 7 + + # Create unrefined section angles (7 sections) + # These will be mapped to panels via refined_panel_mapping + theta_unrefined = deg2rad.([10.0, 15.0, 20.0, 25.0, 20.0, 15.0, 10.0]) + delta_unrefined = deg2rad.([5.0, 7.5, 10.0, 12.5, 10.0, 7.5, 5.0]) + + # Apply using unrefined_deform! + VortexStepMethod.unrefined_deform!(wing, theta_unrefined, delta_unrefined) + VortexStepMethod.reinit!(body_aero; refine_mesh=false) + + # Each panel should have the delta from its mapped unrefined section + for i in 1:wing.n_panels + unrefined_idx = wing.refined_panel_mapping[i] + expected_delta = delta_unrefined[unrefined_idx] + @test body_aero.panels[i].delta ≈ expected_delta atol=1e-6 + end + end end From 6a7aca53df8e04a6260305f67b97441cc290f9cf Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sat, 6 Dec 2025 16:29:58 +0100 Subject: [PATCH 37/86] Rename to more logical name --- test/solver/test_unrefined_dist.jl | 144 +++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 test/solver/test_unrefined_dist.jl diff --git a/test/solver/test_unrefined_dist.jl b/test/solver/test_unrefined_dist.jl new file mode 100644 index 00000000..219cc65e --- /dev/null +++ b/test/solver/test_unrefined_dist.jl @@ -0,0 +1,144 @@ +using VortexStepMethod +using LinearAlgebra +using Test + +@testset "Unrefined Arrays Tests" begin + @testset "Unrefined section array aggregation" begin + # Create a simple wing with unrefined sections + n_panels = 20 + n_unrefined_sections = 5 # 5 unrefined sections + + # Create a test wing settings file + settings_file = create_temp_wing_settings("solver", "solver_test_wing.yaml"; alpha=5.0, beta=0.0, wind_speed=10.0) + + try + # Modify settings to use specific panel configuration + settings = VSMSettings(settings_file) + settings.wings[1].n_panels = n_panels + settings.solver_settings.n_panels = n_panels + + # Create wing and solver + wing = Wing(settings) + body_aero = BodyAerodynamics([wing]) + solver = Solver(body_aero, settings) + + # Set conditions and solve + va = [10.0, 0.0, 0.0] + set_va!(body_aero, va) + sol = solve!(solver, body_aero) + + # Test 1: Unrefined arrays exist and have correct size + @test length(sol.cl_unrefined_dist) == wing.n_unrefined_sections + @test length(sol.cd_unrefined_dist) == wing.n_unrefined_sections + @test length(sol.cm_unrefined_dist) == wing.n_unrefined_sections + + # Test 2: Unrefined arrays are not all zeros (solver computed them) + @test !all(sol.cl_unrefined_dist .== 0.0) + @test !all(sol.cd_unrefined_dist .== 0.0) + + # Test 3: Verify unrefined coefficients are averaged from refined panels + # refined_panel_mapping maps each refined panel to its unrefined section index + for unrefined_idx in 1:wing.n_unrefined_sections + # Find all refined panels that map to this unrefined section + refined_panel_indices = findall(x -> x == unrefined_idx, wing.refined_panel_mapping) + + if !isempty(refined_panel_indices) + # Calculate expected average from refined panel coefficients + expected_cl = sum(sol.cl_dist[refined_panel_indices]) / length(refined_panel_indices) + expected_cd = sum(sol.cd_dist[refined_panel_indices]) / length(refined_panel_indices) + expected_cm = sum(sol.cm_dist[refined_panel_indices]) / length(refined_panel_indices) + + # Check if unrefined coefficients match expected averages + # Handle NaN values that can occur in INVISCID models + if isnan(expected_cl) + @test isnan(sol.cl_unrefined_dist[unrefined_idx]) + else + @test isapprox(sol.cl_unrefined_dist[unrefined_idx], expected_cl, rtol=1e-10) + end + if isnan(expected_cd) + @test isnan(sol.cd_unrefined_dist[unrefined_idx]) + else + @test isapprox(sol.cd_unrefined_dist[unrefined_idx], expected_cd, rtol=1e-10) + end + if isnan(expected_cm) + @test isnan(sol.cm_unrefined_dist[unrefined_idx]) + else + @test isapprox(sol.cm_unrefined_dist[unrefined_idx], expected_cm, rtol=1e-10) + end + end + end + + # Test 4: Verify physical consistency (lift coefficients should be positive at positive AoA) + # Skip test if values are NaN + if !any(isnan.(sol.cl_unrefined_dist)) + @test all(sol.cl_unrefined_dist .> 0.0) + end + + finally + rm(settings_file; force=true) + end + end + + @testset "Unrefined arrays with different panel counts" begin + # Test with various panel/section combinations + test_cases = [ + (n_panels=40, n_unrefined_expected=21), # From YAML file sections + (n_panels=30, n_unrefined_expected=21), + (n_panels=24, n_unrefined_expected=21), + ] + + for (n_panels, n_unrefined_expected) in test_cases + settings_file = create_temp_wing_settings("solver", "solver_test_wing.yaml"; alpha=5.0, beta=0.0, wind_speed=10.0) + + try + settings = VSMSettings(settings_file) + settings.wings[1].n_panels = n_panels + settings.solver_settings.n_panels = n_panels + + wing = Wing(settings) + body_aero = BodyAerodynamics([wing]) + solver = Solver(body_aero, settings) + + va = [10.0, 0.0, 0.0] + set_va!(body_aero, va) + sol = solve!(solver, body_aero) + + # Verify arrays have correct size + @test length(sol.cl_unrefined_dist) == wing.n_unrefined_sections + @test length(sol.cd_unrefined_dist) == wing.n_unrefined_sections + @test length(sol.cm_unrefined_dist) == wing.n_unrefined_sections + + # Verify unrefined coefficients are computed correctly using mapping + for unrefined_idx in 1:wing.n_unrefined_sections + refined_panel_indices = findall(x -> x == unrefined_idx, wing.refined_panel_mapping) + + if !isempty(refined_panel_indices) + expected_cl = sum(sol.cl_dist[refined_panel_indices]) / length(refined_panel_indices) + expected_cd = sum(sol.cd_dist[refined_panel_indices]) / length(refined_panel_indices) + expected_cm = sum(sol.cm_dist[refined_panel_indices]) / length(refined_panel_indices) + + # Handle NaN for all coefficients + if isnan(expected_cl) + @test isnan(sol.cl_unrefined_dist[unrefined_idx]) + else + @test isapprox(sol.cl_unrefined_dist[unrefined_idx], expected_cl, rtol=1e-10) + end + if isnan(expected_cd) + @test isnan(sol.cd_unrefined_dist[unrefined_idx]) + else + @test isapprox(sol.cd_unrefined_dist[unrefined_idx], expected_cd, rtol=1e-10) + end + if isnan(expected_cm) + @test isnan(sol.cm_unrefined_dist[unrefined_idx]) + else + @test isapprox(sol.cm_unrefined_dist[unrefined_idx], expected_cm, rtol=1e-10) + end + end + end + + finally + rm(settings_file; force=true) + end + end + end +end From f13015779bde05e1ee79b4448d3f22e046fd003d Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sat, 6 Dec 2025 16:30:37 +0100 Subject: [PATCH 38/86] Add claude md --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 04fba002..6232db14 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -Manifest.toml +Manifest*.toml .vscode/settings.json venv results/TUDELFT_V3_LEI_KITE/polars/$C_L$ vs $C_D$.pdf @@ -9,3 +9,4 @@ results/TUDELFT_V3_LEI_KITE/polars/tutorial_testing_stall_model_n_panels_54_dist !test/data/*.bin Manifest-v1.11.toml Manifest-v1.10.toml +CLAUDE.md From ddfc633fc6a4f212bf3435022c59a059a314c44d Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sat, 6 Dec 2025 16:30:59 +0100 Subject: [PATCH 39/86] Rename --- docs/src/private_functions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/private_functions.md b/docs/src/private_functions.md index d99dc45b..3646579c 100644 --- a/docs/src/private_functions.md +++ b/docs/src/private_functions.md @@ -7,5 +7,5 @@ CurrentModule = VortexStepMethod calculate_AIC_matrices! update_panel_properties! calculate_inertia_tensor -group_deform! +unrefined_deform! ``` \ No newline at end of file From 4c16cde3b539c40c5ed21e444db0cf6f2b2829cf Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sat, 6 Dec 2025 16:31:22 +0100 Subject: [PATCH 40/86] Simpler example, angle at wingtips --- examples/ram_air_kite.jl | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/examples/ram_air_kite.jl b/examples/ram_air_kite.jl index 600acb7a..cc180023 100644 --- a/examples/ram_air_kite.jl +++ b/examples/ram_air_kite.jl @@ -6,13 +6,13 @@ PLOT = true PRN = true USE_TEX = false DEFORM = true -LINEARIZE = true +LINEARIZE = false # Create wing geometry wing = ObjWing( joinpath("data", "ram_air_kite", "ram_air_kite_body.obj"), joinpath("data", "ram_air_kite", "ram_air_kite_foil.dat"); - n_unrefined_sections=4, + n_unrefined_sections=2, prn=PRN ) body_aero = BodyAerodynamics([wing];) @@ -20,9 +20,8 @@ println("First init") @time VortexStepMethod.reinit!(body_aero) if DEFORM - # Linear interpolation of alpha from 10° at one tip to 0° at the other println("Deform") - @time VortexStepMethod.unrefined_deform!(wing, deg2rad.([10,20,10,0]), deg2rad.([-10,0,-10,0]); smooth=true) + @time VortexStepMethod.unrefined_deform!(wing, deg2rad.([-10,0]), deg2rad.([0,0]); smooth=true) println("Deform init") @time VortexStepMethod.reinit!(body_aero; init_aero=false) end From cd1cc5b0272f4da595a475c05477db0b88b6c489 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sat, 6 Dec 2025 17:00:47 +0100 Subject: [PATCH 41/86] Add unreleased news --- NEWS.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/NEWS.md b/NEWS.md index d368160a..e7493c1b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,27 @@ +## VortexStepMethod [Unreleased] +### Changed +- Unified `Wing` and `RamAirWing` into single `Wing` type (`RamAirWing` now alias for `ObjWing`) +- Renamed `ram_geometry.jl` to `obj_geometry.jl` +- Wing geometry uses unrefined sections with automatic panel-to-section mapping +- Consistent naming: variables ending in `_dist` are per-panel, `_unrefined_dist` per unrefined section +- `VSMSolution` field names: `panel_width_array` → `width_dist`, `alpha_array` → `alpha_dist`, etc. +- Enhanced Makie extension with `plot_combined_analysis` for combined plotting + +### Added +- `n_unrefined_sections` field in `Wing` for tracking pre-refinement sections +- `refined_panel_mapping` for automatic panel-to-section association +- Unrefined distribution fields in `VSMSolution`: `cl_unrefined_dist`, `cd_unrefined_dist`, `cm_unrefined_dist`, `alpha_unrefined_dist`, `moment_unrefined_dist` +- `PanelDistribution.NONE` for wings already refined +- Kwarg `sort_sections` for section ordering +- YAML wing deformation tests +- Unrefined distribution tests + +### Removed +- Panel grouping (replaced with unrefined section mapping) +- `PanelGroupingMethod` enum (deprecated, grouping automatic via mapping) +- `n_groups` and `grouping_method` from settings files and structs +- `n_groups` field from `WingSettings` and `SolverSettings` + ## VortexStepMethod v2.3.0 2025-10-16 ### Added - A Makie plotting extension. From 135a71394f5852a30b756923dcf3d3ff33ef34d6 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sat, 6 Dec 2025 17:01:28 +0100 Subject: [PATCH 42/86] Remove last instances of groups --- data/TUDELFT_V3_KITE/vsm_settings.yaml | 2 -- data/pyramid_model/vsm_settings.yaml | 2 -- data/ram_air_kite/vsm_settings.yaml | 7 ----- data/ram_air_kite/vsm_settings_dual.yaml | 2 -- docs/src/tips_and_tricks.md | 27 ++++++----------- examples/V3_kite.jl | 4 +-- examples/pyramid_model.jl | 4 +-- examples/rectangular_wing.jl | 2 +- examples/stall_model.jl | 4 +-- ext/VortexStepMethodMakieExt.jl | 24 +++++++-------- src/VortexStepMethod.jl | 17 +---------- src/obj_geometry.jl | 25 +++------------- src/settings.jl | 8 +---- src/wing_geometry.jl | 23 ++------------ src/yaml_geometry.jl | 30 +++---------------- test/plotting/test_plotting.jl | 24 +++++++-------- test/ram_geometry/test_kite_geometry.jl | 2 +- .../test_yaml_wing_deformation.jl | 2 +- 18 files changed, 54 insertions(+), 155 deletions(-) diff --git a/data/TUDELFT_V3_KITE/vsm_settings.yaml b/data/TUDELFT_V3_KITE/vsm_settings.yaml index cef41285..9f185704 100644 --- a/data/TUDELFT_V3_KITE/vsm_settings.yaml +++ b/data/TUDELFT_V3_KITE/vsm_settings.yaml @@ -30,7 +30,6 @@ # NEWTON: Newton-Raphson nonlinear solver # # USAGE NOTES: -# - n_panels should be divisible by n_groups for proper load balancing # - Higher n_panels improves accuracy but increases computation time # - Lower relaxation_factor if convergence issues occur @@ -46,7 +45,6 @@ wings: - name: V3_Kite # Wing identifier for output labeling geometry_file: data/TUDELFT_V3_KITE/aero_geometry.yaml n_panels: 36 # Total number of panels along wingspan - n_groups: 1 # Number of panel groups (must divide n_panels) spanwise_panel_distribution: LINEAR # Panel spacing algorithm spanwise_direction: [0.0, 1.0, 0.0] # Unit vector defining wingspan direction remove_nan: true # Remove NaN values from polar data diff --git a/data/pyramid_model/vsm_settings.yaml b/data/pyramid_model/vsm_settings.yaml index 93ba2ca8..5ab7053d 100644 --- a/data/pyramid_model/vsm_settings.yaml +++ b/data/pyramid_model/vsm_settings.yaml @@ -30,7 +30,6 @@ # NEWTON: Newton-Raphson nonlinear solver # # USAGE NOTES: -# - n_panels should be divisible by n_groups for proper load balancing # - Higher n_panels improves accuracy but increases computation time # - Lower relaxation_factor if convergence issues occur @@ -46,7 +45,6 @@ wings: - name: V3_Kite # Wing identifier for output labeling geometry_file: data/pyramid_model/wing_geometry.yaml n_panels: 2 # Total number of panels along wingspan - n_groups: 1 # Number of panel groups (must divide n_panels) spanwise_panel_distribution: LINEAR # Panel spacing algorithm spanwise_direction: [0.0, 1.0, 0.0] # Unit vector defining wingspan direction remove_nan: true # Remove NaN values from polar data diff --git a/data/ram_air_kite/vsm_settings.yaml b/data/ram_air_kite/vsm_settings.yaml index 8f726240..0726e7f8 100644 --- a/data/ram_air_kite/vsm_settings.yaml +++ b/data/ram_air_kite/vsm_settings.yaml @@ -10,21 +10,14 @@ PanelDistribution: InitialGammaDistribution: ELLIPTIC: Elliptic distribution ZEROS: Constant distribution -PanelGroupingMethod: - EQUAL_SIZE: Divide panels into equally-sized sequential groups - REFINE: Group refined panels by their original unrefined section - wings: - name: main_wing n_panels: 40 - n_groups: 40 spanwise_panel_distribution: LINEAR spanwise_direction: [0.0, 1.0, 0.0] - grouping_method: EQUAL_SIZE remove_nan: true solver_settings: n_panels: 40 - n_groups: 40 aerodynamic_model_type: VSM density: 1.225 # air density [kg/m³] max_iterations: 1500 diff --git a/data/ram_air_kite/vsm_settings_dual.yaml b/data/ram_air_kite/vsm_settings_dual.yaml index 307cf14d..5c4a9359 100644 --- a/data/ram_air_kite/vsm_settings_dual.yaml +++ b/data/ram_air_kite/vsm_settings_dual.yaml @@ -14,13 +14,11 @@ InitialGammaDistribution: wings: - name: main_wing n_panels: 40 - n_groups: 40 spanwise_panel_distribution: LINEAR spanwise_direction: [0.0, 1.0, 0.0] remove_nan: true - name: tail n_panels: 20 - n_groups: 20 spanwise_panel_distribution: COSINE spanwise_direction: [0.0, 1.1, 0.0] remove_nan: false diff --git a/docs/src/tips_and_tricks.md b/docs/src/tips_and_tricks.md index 63cf87d3..6e8d532f 100644 --- a/docs/src/tips_and_tricks.md +++ b/docs/src/tips_and_tricks.md @@ -10,37 +10,28 @@ The following bodies can be simulated: To build the geometry of a RAM-air kite, a 3D .obj file can be used as input. In addition a `.dat` file is needed. It should have two columns, one for the `x` and one for the `y` coordinate of the 2D polar that is used. -## Panel Grouping Methods -When creating a wing, you can specify how panels should be grouped for moment and force calculations using the `grouping_method` parameter. Two methods are available: +## Unrefined Section Distribution +When creating a wing, panel forces and moments are automatically computed for each unrefined section. The unrefined sections correspond to the original geometry sections you define, while panels represent the refined mesh used for aerodynamic calculations. -### EQUAL_SIZE (Default) -Divides refined panels into equally-sized sequential groups. This is the original behavior. +### How It Works +The solver automatically tracks which panels belong to which original unrefined section. After refinement (e.g., splitting each section into multiple panels), the aerodynamic forces and moments are aggregated back to the unrefined section level. ```julia -wing = Wing(40; n_groups=4, grouping_method=EQUAL_SIZE) -``` - -In this example, with 40 panels and 4 groups, each group will contain 10 consecutive panels (panels 1-10, 11-20, 21-30, 31-40). - -### REFINE -Groups refined panels back to their original unrefined section. This is useful when you want group moments and forces to represent the original wing structure, regardless of panel refinement. - -```julia -# Create wing with 4 unrefined sections (3 panels) -wing = Wing(40; n_groups=3, grouping_method=REFINE) +# Create wing with 4 sections, refined to 40 panels +wing = Wing(40) add_section!(wing, [0, 5, 0], [1, 5, 0], INVISCID) # Section 1 add_section!(wing, [0, 2.5, 0], [1, 2.5, 0], INVISCID) # Section 2 add_section!(wing, [0, 0, 0], [1, 0, 0], INVISCID) # Section 3 add_section!(wing, [0, -5, 0], [1, -5, 0], INVISCID) # Section 4 ``` -**Important:** When using `REFINE`, `n_groups` must equal the number of unrefined panels (number of sections - 1). The solver will automatically map each refined panel to its closest original unrefined panel and sum their moments and forces accordingly. +The 40 panels are distributed across the 3 unrefined panels (sections 1-2, 2-3, 3-4). Forces and moments are computed per panel during the solve, then automatically aggregated to the 3 unrefined panels for output. -This is particularly useful for: +This approach is useful for: - LEI kites where you want loads per rib - Wings with discrete control surfaces - Cases where physical structure doesn't align with uniform panel distribution -- Dynamic simulations where you have fewer structural segments than panels needed for accurate VSM aerodynamics. For example, a 6-segment structural model can be combined with 40-panel aerodynamics by using `n_groups=6` and `grouping_method=REFINE` to map aerodynamic loads back to the structural segments. +- Dynamic simulations where you have fewer structural segments than panels needed for accurate VSM aerodynamics. For example, a 6-segment structural model can be combined with 40-panel aerodynamics, with loads automatically mapped back to the 6 structural segments. ## RAM-air kite model If running the example `ram_air_kite.jl` fails, try to run the `cleanup.jl` script and then try again. Background: this example caches the calculated polars. Reading cached polars can fail after an update. diff --git a/examples/V3_kite.jl b/examples/V3_kite.jl index 4833c776..560fd98d 100644 --- a/examples/V3_kite.jl +++ b/examples/V3_kite.jl @@ -50,7 +50,7 @@ PLOT && plot_polars( side_slip=sideslip_deg, v_a=wind_speed, title="$(wing.n_panels)_panels_$(wing.spanwise_distribution)_from_yaml_settings", - data_type=".pdf", + data_type=".png", is_save=false, is_show=true, use_tex=USE_TEX @@ -80,7 +80,7 @@ PLOT && plot_distribution( [results], ["VSM"]; title="CAD_spanwise_distributions_alpha_$(round(angle_of_attack_deg, digits=1))_delta_$(round(sideslip_deg, digits=1))_yaw_$(round(yaw_rate, digits=1))_v_a_$(round(wind_speed, digits=1))", - data_type=".pdf", + data_type=".png", is_save=false, is_show=true, use_tex=USE_TEX diff --git a/examples/pyramid_model.jl b/examples/pyramid_model.jl index a67d8bb5..43d4220a 100644 --- a/examples/pyramid_model.jl +++ b/examples/pyramid_model.jl @@ -39,7 +39,7 @@ PLOT && plot_polars( side_slip=sideslip_deg, v_a=wind_speed, title="$(wing.n_panels)_panels_$(wing.spanwise_distribution)_pyramid_model", - data_type=".pdf", + data_type=".png", is_save=false, is_show=true, use_tex=USE_TEX @@ -67,7 +67,7 @@ PLOT && plot_distribution( [results], ["VSM"]; title="pyramid_spanwise_distributions_alpha_$(round(angle_of_attack_deg, digits=1))_delta_$(round(sideslip_deg, digits=1))_yaw_$(round(yaw_rate, digits=1))_v_a_$(round(wind_speed, digits=1))", - data_type=".pdf", + data_type=".png", is_save=false, is_show=true, use_tex=USE_TEX diff --git a/examples/rectangular_wing.jl b/examples/rectangular_wing.jl index 360eb5ce..330de483 100644 --- a/examples/rectangular_wing.jl +++ b/examples/rectangular_wing.jl @@ -57,7 +57,7 @@ println("Projected area = $(round(results_vsm["projected_area"], digits=4)) m²" PLOT && plot_geometry( body_aero, "Rectangular_wing_geometry"; - data_type=".pdf", + data_type=".png", save_path=".", is_save=false, is_show=true, diff --git a/examples/stall_model.jl b/examples/stall_model.jl index 510fe094..b6d01e92 100644 --- a/examples/stall_model.jl +++ b/examples/stall_model.jl @@ -89,7 +89,7 @@ PLOT && plot_distribution( [results, results_with_stall], ["VSM", "VSM with stall correction"]; title="CAD_spanwise_distributions_alpha_$(round(aoa, digits=1))_delta_$(round(side_slip, digits=1))_yaw_$(round(yaw_rate, digits=1))_v_a_$(round(v_a, digits=1))", - data_type=".pdf", + data_type=".png", save_path=joinpath(save_folder, "spanwise_distributions"), is_save=false, is_show=true, @@ -123,7 +123,7 @@ PLOT && plot_polars( side_slip=0, v_a=10, title="tutorial_testing_stall_model_n_panels_$(n_panels)_distribution_$(spanwise_distribution)_unrefined_$(CAD_wing.n_unrefined_sections)", - data_type=".pdf", + data_type=".png", save_path=joinpath(save_folder, "polars"), is_save=true, is_show=true, diff --git a/ext/VortexStepMethodMakieExt.jl b/ext/VortexStepMethodMakieExt.jl index 1f93c4f7..badf35c2 100644 --- a/ext/VortexStepMethodMakieExt.jl +++ b/ext/VortexStepMethodMakieExt.jl @@ -237,7 +237,7 @@ function Makie.plot(body_aero::VortexStepMethod.BodyAerodynamics; size = (1200, end """ - save_plot(fig, save_path, title; data_type=".pdf") + save_plot(fig, save_path, title; data_type=".png") Save a Makie figure to a file. @@ -247,9 +247,9 @@ Save a Makie figure to a file. - `title`: Title of the plot # Keyword arguments -- `data_type`: File extension (default: ".pdf") +- `data_type`: File extension (default: ".png", also supports ".jpeg") """ -function VortexStepMethod.save_plot(fig, save_path, title; data_type=".pdf") +function VortexStepMethod.save_plot(fig, save_path, title; data_type=".png") isnothing(save_path) && throw(ArgumentError("save_path should be provided")) !isdir(save_path) && mkpath(save_path) @@ -434,7 +434,7 @@ end """ plot_geometry(body_aero::BodyAerodynamics, title; - data_type=".pdf", save_path=nothing, + data_type=".png", save_path=nothing, is_save=false, is_show=false, view_elevation=15, view_azimuth=-120, use_tex=false) @@ -445,7 +445,7 @@ Plot wing geometry from different viewpoints using Makie. - `title`: plot title # Keyword arguments: -- `data_type`: File extension (default: ".pdf") +- `data_type`: File extension (default: ".png", also supports ".jpeg") - `save_path`: Path for saving (default: nothing) - `is_save`: Whether to save (default: false) - `is_show`: Whether to display (default: false) @@ -454,7 +454,7 @@ Plot wing geometry from different viewpoints using Makie. - `use_tex`: Ignored for Makie (default: false) """ function VortexStepMethod.plot_geometry(body_aero::BodyAerodynamics, title; - data_type=".pdf", + data_type=".png", save_path=nothing, is_save=false, is_show=false, @@ -491,7 +491,7 @@ end """ plot_distribution(y_coordinates_list, results_list, label_list; - title="spanwise_distribution", data_type=".pdf", + title="spanwise_distribution", data_type=".png", save_path=nothing, is_save=false, is_show=true, use_tex=false) Plot spanwise distributions of aerodynamic properties using Makie. @@ -503,7 +503,7 @@ Plot spanwise distributions of aerodynamic properties using Makie. # Keyword arguments - `title`: Plot title (default: "spanwise_distribution") -- `data_type`: File extension (default: ".pdf") +- `data_type`: File extension (default: ".png", also supports ".jpeg") - `save_path`: Path to save plots (default: nothing) - `is_save`: Whether to save (default: false) - `is_show`: Whether to display (default: true) @@ -511,7 +511,7 @@ Plot spanwise distributions of aerodynamic properties using Makie. """ function VortexStepMethod.plot_distribution(y_coordinates_list, results_list, label_list; title="spanwise_distribution", - data_type=".pdf", + data_type=".png", save_path=nothing, is_save=false, is_show=true, @@ -703,7 +703,7 @@ end literature_path_list=String[], angle_range=range(0, 20, 2), angle_type="angle_of_attack", angle_of_attack=0.0, side_slip=0.0, v_a=10.0, - title="polar", data_type=".pdf", save_path=nothing, + title="polar", data_type=".png", save_path=nothing, is_save=true, is_show=true, use_tex=false) Plot polar data comparing different solvers using Makie. @@ -721,7 +721,7 @@ Plot polar data comparing different solvers using Makie. - `side_slip`: Side slip angle [rad] (default: 0.0) - `v_a`: Wind speed [m/s] (default: 10.0) - `title`: Plot title -- `data_type`: File extension (default: ".pdf") +- `data_type`: File extension (default: ".png", also supports ".jpeg") - `save_path`: Path to save (default: nothing) - `is_save`: Whether to save (default: true) - `is_show`: Whether to display (default: true) @@ -738,7 +738,7 @@ function VortexStepMethod.plot_polars( side_slip=0.0, v_a=10.0, title="polar", - data_type=".pdf", + data_type=".png", save_path=nothing, is_save=true, is_show=true, diff --git a/src/VortexStepMethod.jl b/src/VortexStepMethod.jl index 92710573..e4c730cd 100644 --- a/src/VortexStepMethod.jl +++ b/src/VortexStepMethod.jl @@ -36,8 +36,7 @@ export calculate_span, calculate_projected_area export MVec3 export Model, VSM, LLT export AeroModel, LEI_AIRFOIL_BREUKELS, POLAR_VECTORS, POLAR_MATRICES, INVISCID -export PanelDistribution, LINEAR, COSINE, COSINE_VAN_GARREL, SPLIT_PROVIDED, UNCHANGED -export PanelGroupingMethod, EQUAL_SIZE, REFINE +export PanelDistribution, LINEAR, COSINE, COSINE_VAN_GARREL, SPLIT_PROVIDED, UNCHANGED, NONE export InitialGammaDistribution, ELLIPTIC, ZEROS export SolverStatus, FEASIBLE, INFEASIBLE, FAILURE export SolverType, LOOP, NONLIN @@ -143,20 +142,6 @@ Enumeration of the implemented panel distributions. NONE # No refinement - sections already refined end -""" - PanelGroupingMethod EQUAL_SIZE REFINE - -**DEPRECATED**: This enum is deprecated and no longer used. -Grouping is now automatically handled via unrefined section mapping. - -Enumeration of methods for grouping panels (legacy). - -# Elements -- EQUAL_SIZE: (Deprecated) Divide panels into equally-sized sequential groups -- REFINE: (Deprecated) Group refined panels back to their original unrefined section -""" -@enum PanelGroupingMethod EQUAL_SIZE REFINE - """ InitialGammaDistribution ELLIPTIC ZEROS diff --git a/src/obj_geometry.jl b/src/obj_geometry.jl index c77e122e..b89874e5 100644 --- a/src/obj_geometry.jl +++ b/src/obj_geometry.jl @@ -392,8 +392,7 @@ The resulting Wing supports deformation through unrefined_deform! and deform! fu - `wind_vel=10.0`: Reference wind velocity for XFoil analysis (m/s) - `mass=1.0`: Wing mass (kg) - `n_panels=56`: Number of aerodynamic panels across wingspan -- `n_groups=4`: Number of control groups for deformation -- `n_sections=n_panels+1`: Number of spanwise cross-sections +- `n_unrefined_sections`: Number of unrefined sections for deformation control (default: inferred from geometry) - `align_to_principal=false`: Align body frame to principal axes of inertia - `spanwise_distribution=UNCHANGED`: Panel distribution type (forced to UNCHANGED for ObjWing) - `remove_nan=true`: Interpolate NaN values in aerodynamic data @@ -412,7 +411,7 @@ wing = ObjWing( "path/to/airfoil.dat"; mass=1.5, n_panels=40, - n_groups=4 + n_unrefined_sections=4 ) # Apply deformation @@ -422,28 +421,12 @@ unrefined_deform!(wing, deg2rad.([5, 10, 5, 0]), deg2rad.([-5, 0, -5, 0])) function ObjWing( obj_path, dat_path; crease_frac=0.9, wind_vel=10., mass=1.0, - n_panels=56, n_sections=nothing, n_unrefined_sections=nothing, n_groups=nothing, + n_panels=56, n_unrefined_sections=nothing, spanwise_distribution=UNCHANGED, spanwise_direction=[0.0, 1.0, 0.0], remove_nan=true, align_to_principal=false, alpha_range=deg2rad.(-5:1:20), delta_range=deg2rad.(-5:1:20), prn=true, - interp_steps=n_panels+1, grouping_method::PanelGroupingMethod=EQUAL_SIZE + interp_steps=n_panels+1 ) - # Handle deprecated parameters - if !isnothing(n_groups) - if !isnothing(n_unrefined_sections) - error("Cannot specify both n_groups and n_unrefined_sections. Use n_unrefined_sections only.") - end - @warn "Parameter n_groups is deprecated. Use n_unrefined_sections instead." maxlog=1 - n_unrefined_sections = n_groups - end - - if !isnothing(n_sections) - @warn "Parameter n_sections is deprecated. It is now always n_panels+1 for refined sections. Use n_unrefined_sections to control initial sections." maxlog=1 - end - - if grouping_method != EQUAL_SIZE - @warn "Parameter grouping_method is deprecated and ignored. Grouping is now always by unrefined sections." maxlog=1 - end # Force NONE distribution for ObjWing if spanwise_distribution != NONE diff --git a/src/settings.jl b/src/settings.jl index 4010b8d9..9c6bd81f 100644 --- a/src/settings.jl +++ b/src/settings.jl @@ -11,16 +11,13 @@ end obj_file::String = "" # path to .obj geometry file dat_file::String = "" # path to .dat airfoil file n_panels::Int64 = 40 - n_groups::Int64 = 40 spanwise_panel_distribution::PanelDistribution = LINEAR spanwise_direction::MVec3 = [0.0, 1.0, 0.0] - grouping_method::PanelGroupingMethod = EQUAL_SIZE remove_nan = true end @with_kw mutable struct SolverSettings n_panels::Int64 = 40 - n_groups::Int64 = 40 aerodynamic_model_type::Model = VSM solver_type::String = "LOOP" # type of solver density::Float64 = 1.225 # air density [kg/m³] @@ -63,8 +60,7 @@ function VSMSettings(filename; data_prefix=true) # Convert wing settings manually due to enum conversions n_panels = 0 - n_groups = 0 - + if haskey(data, "wings") for wing_data in data["wings"] wing = WingSettings() @@ -92,7 +88,6 @@ function VSMSettings(filename; data_prefix=true) push!(vsm_settings.wings, wing) n_panels += wing.n_panels - # n_unrefined_sections will be set when wing is created/initialized end end @@ -119,7 +114,6 @@ function VSMSettings(filename; data_prefix=true) # Override with calculated totals vsm_settings.solver_settings.n_panels = n_panels - vsm_settings.solver_settings.n_groups = n_groups end return vsm_settings diff --git a/src/wing_geometry.jl b/src/wing_geometry.jl index 2345bd46..3a11fb08 100644 --- a/src/wing_geometry.jl +++ b/src/wing_geometry.jl @@ -255,11 +255,9 @@ end """ Wing(n_panels::Int; n_unrefined_sections=nothing, - n_groups=nothing, spanwise_distribution::PanelDistribution=LINEAR, spanwise_direction::PosVector=MVec3([0.0, 1.0, 0.0]), - remove_nan::Bool=true, - grouping_method::PanelGroupingMethod=EQUAL_SIZE) + remove_nan::Bool=true) Constructor for a [Wing](@ref) struct with default values that initializes the sections and refined sections as empty arrays. Creates a basic wing suitable for YAML-based construction. @@ -267,32 +265,15 @@ and refined sections as empty arrays. Creates a basic wing suitable for YAML-bas # Parameters - `n_panels::Int`: Number of panels in aerodynamic mesh - `n_unrefined_sections::Int`: Number of unrefined sections (inferred from added sections for YAML wings) -- `n_groups::Int`: DEPRECATED - use n_unrefined_sections instead - `spanwise_distribution`::PanelDistribution = LINEAR: [PanelDistribution](@ref) - `spanwise_direction::MVec3` = MVec3([0.0, 1.0, 0.0]): Wing span direction vector - `remove_nan::Bool`: Wether to remove the NaNs from interpolations or not -- `grouping_method::PanelGroupingMethod` = EQUAL_SIZE: DEPRECATED - grouping is now always by unrefined sections """ function Wing(n_panels::Int; n_unrefined_sections=nothing, - n_groups=nothing, spanwise_distribution::PanelDistribution=LINEAR, spanwise_direction::PosVector=MVec3([0.0, 1.0, 0.0]), - remove_nan=true, - grouping_method::PanelGroupingMethod=EQUAL_SIZE) - - # Handle deprecated parameters - if !isnothing(n_groups) - if !isnothing(n_unrefined_sections) - error("Cannot specify both n_groups and n_unrefined_sections. Use n_unrefined_sections only.") - end - @warn "Parameter n_groups is deprecated. Use n_unrefined_sections instead." maxlog=1 - n_unrefined_sections = n_groups - end - - if grouping_method != EQUAL_SIZE - @warn "Parameter grouping_method is deprecated and ignored. Grouping is now always by unrefined sections." maxlog=1 - end + remove_nan=true) # For YAML wings, n_unrefined_sections will be set when sections are added # Set to 0 as placeholder for now diff --git a/src/yaml_geometry.jl b/src/yaml_geometry.jl index a24492e2..60571026 100644 --- a/src/yaml_geometry.jl +++ b/src/yaml_geometry.jl @@ -148,7 +148,7 @@ function load_polar_data(csv_file_path::String) end """ - Wing(geometry_file::String; n_panels=20, n_groups=1, spanwise_distribution=LINEAR, + Wing(geometry_file::String; n_panels=20, spanwise_distribution=LINEAR, spanwise_direction=[0.0, 1.0, 0.0], remove_nan=true, prn=false) Constructs a `Wing` object from a YAML geometry file. @@ -158,7 +158,6 @@ Constructs a `Wing` object from a YAML geometry file. # Keyword Arguments - `n_panels::Int`: Number of spanwise panels (default: 20). -- `n_groups::Int`: Number of grouped sections across the span (default: 1). Must divide `n_panels`. - `spanwise_distribution`: Spanwise panel distribution type (default: `LINEAR`). - `spanwise_direction::Vector{Float64}`: Direction of the spanwise axis (default: `[0.0, 1.0, 0.0]`). Must be the global Y axis. - `remove_nan::Bool`: Remove NaN values from the geometry (default: `true`). @@ -171,43 +170,24 @@ Constructs a `Wing` object from a YAML geometry file. This function reads a YAML configuration file to define the geometry and airfoil data for a multi-section wing. Each section and corresponding airfoil is parsed from the YAML file, polar data is loaded, and each section is added to the wing. The geometry logic currently assumes the spanwise direction is `[0.0, 1.0, 0.0]` (aligned with the global Y axis). +The number of unrefined sections is automatically inferred from the sections in the geometry file. # Errors -- Throws an `ArgumentError` if `n_panels` is not divisible by `n_groups`. - Throws an `ArgumentError` if `spanwise_direction` is not `[0.0, 1.0, 0.0]`. # Example ```julia -wing = Wing("wing_geometry.yaml"; n_panels=30, n_groups=2, prn=true) +wing = Wing("wing_geometry.yaml"; n_panels=30, prn=true) ``` """ function Wing( geometry_file::String; n_panels=20, - n_unrefined_sections=nothing, - n_groups=nothing, spanwise_distribution=LINEAR, spanwise_direction=[0.0, 1.0, 0.0], remove_nan=true, - prn=false, - grouping_method::PanelGroupingMethod=EQUAL_SIZE + prn=false ) - # Handle deprecated parameters - if !isnothing(n_groups) - if !isnothing(n_unrefined_sections) - error("Cannot specify both n_groups and n_unrefined_sections. Use n_unrefined_sections only.") - end - @warn "Parameter n_groups is deprecated. For YAML wings, n_unrefined_sections is inferred from added sections." maxlog=1 - end - - if grouping_method != EQUAL_SIZE - @warn "Parameter grouping_method is deprecated and ignored. Grouping is now always by unrefined sections." maxlog=1 - end - - # For YAML wings, n_unrefined_sections is inferred from the number of sections added - if !isnothing(n_unrefined_sections) - @warn "For YAML wings, n_unrefined_sections is automatically inferred from the sections in the geometry file. The parameter is ignored." maxlog=1 - end !isapprox(spanwise_direction, [0.0, 1.0, 0.0]) && throw(ArgumentError("Spanwise direction has to be [0.0, 1.0, 0.0], not $spanwise_direction")) @@ -348,7 +328,6 @@ function Wing(settings::VSMSettings) # Use YAML geometry constructor Wing(wing_settings.geometry_file; n_panels=wing_settings.n_panels, - n_groups=wing_settings.n_groups, spanwise_distribution=wing_settings.spanwise_panel_distribution, remove_nan=wing_settings.remove_nan ) @@ -358,7 +337,6 @@ function Wing(settings::VSMSettings) wing_settings.obj_file, wing_settings.dat_file; n_panels=wing_settings.n_panels, - n_groups=wing_settings.n_groups, spanwise_distribution=wing_settings.spanwise_panel_distribution, spanwise_direction=wing_settings.spanwise_direction, remove_nan=wing_settings.remove_nan diff --git a/test/plotting/test_plotting.jl b/test/plotting/test_plotting.jl index eba66aa2..0bcfc6cc 100644 --- a/test/plotting/test_plotting.jl +++ b/test/plotting/test_plotting.jl @@ -70,19 +70,19 @@ end fig = plot_geometry( body_aero, "Rectangular_wing_geometry"; - data_type=".pdf", + data_type=".png", save_path=save_dir, is_save=true, is_show=false) @test fig isa Figure - @test isfile(joinpath(save_dir, "Rectangular_wing_geometry_angled_view.pdf")) - safe_rm(joinpath(save_dir, "Rectangular_wing_geometry_angled_view.pdf")) - @test isfile(joinpath(save_dir, "Rectangular_wing_geometry_front_view.pdf")) - safe_rm(joinpath(save_dir, "Rectangular_wing_geometry_front_view.pdf")) - @test isfile(joinpath(save_dir, "Rectangular_wing_geometry_side_view.pdf")) - safe_rm(joinpath(save_dir, "Rectangular_wing_geometry_side_view.pdf")) - @test isfile(joinpath(save_dir, "Rectangular_wing_geometry_top_view.pdf")) - safe_rm(joinpath(save_dir, "Rectangular_wing_geometry_top_view.pdf")) + @test isfile(joinpath(save_dir, "Rectangular_wing_geometry_angled_view.png")) + safe_rm(joinpath(save_dir, "Rectangular_wing_geometry_angled_view.png")) + @test isfile(joinpath(save_dir, "Rectangular_wing_geometry_front_view.png")) + safe_rm(joinpath(save_dir, "Rectangular_wing_geometry_front_view.png")) + @test isfile(joinpath(save_dir, "Rectangular_wing_geometry_side_view.png")) + safe_rm(joinpath(save_dir, "Rectangular_wing_geometry_side_view.png")) + @test isfile(joinpath(save_dir, "Rectangular_wing_geometry_top_view.png")) + safe_rm(joinpath(save_dir, "Rectangular_wing_geometry_top_view.png")) # Step 5: Initialize the solvers vsm_solver = Solver(body_aero; aerodynamic_model_type=VSM) @@ -114,14 +114,14 @@ end angle_type="angle_of_attack", v_a=v_a, title="Rectangular Wing Polars", - data_type=".pdf", + data_type=".png", save_path=save_dir, is_save=true, is_show=false ) @test fig isa Figure - @test isfile(joinpath(save_dir, "Rectangular_Wing_Polars.pdf")) - safe_rm(joinpath(save_dir, "Rectangular_Wing_Polars.pdf")) + @test isfile(joinpath(save_dir, "Rectangular_Wing_Polars.png")) + safe_rm(joinpath(save_dir, "Rectangular_Wing_Polars.png")) # Step 9: Test polar data plotting body_aero = BodyAerodynamics([ram_wing]) diff --git a/test/ram_geometry/test_kite_geometry.jl b/test/ram_geometry/test_kite_geometry.jl index 3058af89..894664d2 100644 --- a/test/ram_geometry/test_kite_geometry.jl +++ b/test/ram_geometry/test_kite_geometry.jl @@ -169,7 +169,7 @@ using Serialization wing = ObjWing(test_obj_path, test_dat_path; remove_nan=true) @test wing.n_panels == 56 # Default value - @test wing.spanwise_distribution == UNCHANGED + @test wing.spanwise_distribution == NONE @test wing.spanwise_direction ≈ [0.0, 1.0, 0.0] @test length(wing.unrefined_sections) > 0 # Should have sections now @test wing.mass ≈ 1.0 diff --git a/test/yaml_geometry/test_yaml_wing_deformation.jl b/test/yaml_geometry/test_yaml_wing_deformation.jl index d483835a..199d6bc9 100644 --- a/test/yaml_geometry/test_yaml_wing_deformation.jl +++ b/test/yaml_geometry/test_yaml_wing_deformation.jl @@ -90,7 +90,7 @@ using Test @test body_aero.panels[1].delta < body_aero.panels[end].delta # Reset and verify - VortexStepMethod.deform!(wing, zeros(wing.n_unrefined_sections), zeros(wing.n_unrefined_sections)) + VortexStepMethod.deform!(wing, zeros(wing.n_panels), zeros(wing.n_panels)) VortexStepMethod.reinit!(body_aero; refine_mesh=false) for (idx, i) in enumerate(test_indices) From c9febb966eb21a60a67195c0ddbfa37566be6700 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sat, 6 Dec 2025 17:05:41 +0100 Subject: [PATCH 43/86] Removed groups --- test/settings/test_settings.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/settings/test_settings.jl b/test/settings/test_settings.jl index 68566cae..42fb5e5b 100644 --- a/test/settings/test_settings.jl +++ b/test/settings/test_settings.jl @@ -11,6 +11,6 @@ using Test @test vss.wings isa Vector{WingSettings} @test length(vss.wings) == 2 io = IOBuffer(repr(vss)) - @test countlines(io) == 47 # Updated to match new output format + @test countlines(io) == 42 # Updated to match new output format end nothing From b4a90f8caaeffdd9b286dbd5e70c2788688c1f64 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sat, 6 Dec 2025 19:53:16 +0100 Subject: [PATCH 44/86] Add tests for smoothing and non smoothing deform --- data/ram_air_kite/vsm_settings.yaml | 2 +- .../test_yaml_wing_deformation.jl | 66 +++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/data/ram_air_kite/vsm_settings.yaml b/data/ram_air_kite/vsm_settings.yaml index 0726e7f8..92372c10 100644 --- a/data/ram_air_kite/vsm_settings.yaml +++ b/data/ram_air_kite/vsm_settings.yaml @@ -13,7 +13,7 @@ InitialGammaDistribution: wings: - name: main_wing n_panels: 40 - spanwise_panel_distribution: LINEAR + spanwise_panel_distribution: NONE spanwise_direction: [0.0, 1.0, 0.0] remove_nan: true solver_settings: diff --git a/test/yaml_geometry/test_yaml_wing_deformation.jl b/test/yaml_geometry/test_yaml_wing_deformation.jl index 199d6bc9..bf263cc5 100644 --- a/test/yaml_geometry/test_yaml_wing_deformation.jl +++ b/test/yaml_geometry/test_yaml_wing_deformation.jl @@ -235,4 +235,70 @@ using Test @test body_aero.panels[i].delta ≈ expected_delta atol=1e-6 end end + + @testset "Smooth vs Non-Smooth Deformation" begin + # Create test wing with 2 unrefined sections, refined to 40 panels + simple_wing_file = test_data_path("yaml_geometry", "simple_wing.yaml") + wing = Wing(simple_wing_file; n_panels=40) + @test wing.n_unrefined_sections == 2 + + # Define varying input angles at unrefined section level + delta_input = deg2rad.([0.0, 10.0]) + + # Test 1: Non-smooth deformation has step-wise discontinuities + VortexStepMethod.unrefined_deform!(wing, nothing, delta_input; smooth=false) + delta_nonsmooth = copy(wing.delta_dist) + + # Verify step-wise pattern: panels in same unrefined section have identical angles + for i in 1:wing.n_panels + unrefined_idx = wing.refined_panel_mapping[i] + @test delta_nonsmooth[i] ≈ delta_input[unrefined_idx] atol=1e-10 + end + + # Verify discontinuities exist at unrefined section boundaries + # Find boundary indices (where panel mapping changes) + max_gradient_nonsmooth = 0.0 + for i in 1:(wing.n_panels-1) + if wing.refined_panel_mapping[i] != wing.refined_panel_mapping[i+1] + gradient = abs(delta_nonsmooth[i+1] - delta_nonsmooth[i]) + max_gradient_nonsmooth = max(max_gradient_nonsmooth, gradient) + end + end + @test max_gradient_nonsmooth > deg2rad(5.0) # Should have large jumps + + # Test 2: Smooth deformation is continuous + VortexStepMethod.unrefined_deform!(wing, nothing, delta_input; smooth=true) + delta_smooth = copy(wing.delta_dist) + + # Verify gradients between adjacent panels are small + max_gradient_smooth = maximum(abs.(diff(delta_smooth))) + @test max_gradient_smooth < deg2rad(3.0) # Should be smooth + + # Verify no sharp discontinuities + for i in 1:(wing.n_panels-1) + @test abs(delta_smooth[i+1] - delta_smooth[i]) < deg2rad(3.0) + end + + # Test 3: Smoothing reduces maximum gradient + @test max_gradient_smooth < max_gradient_nonsmooth + + # Test 4: Angles match input at unrefined section centers (both modes) + # For non-smooth: extract angle at center panel of each unrefined section + VortexStepMethod.unrefined_deform!(wing, nothing, delta_input; smooth=false) + for i in 1:wing.n_unrefined_sections + # Find panels belonging to this unrefined section + panel_indices = findall(==(i), wing.refined_panel_mapping) + center_panel_idx = panel_indices[div(length(panel_indices), 2) + 1] + @test wing.delta_dist[center_panel_idx] ≈ delta_input[i] atol=1e-10 + end + + # For smooth: angles at center should be close to input (tolerance larger due to smoothing) + VortexStepMethod.unrefined_deform!(wing, nothing, delta_input; smooth=true) + for i in 1:wing.n_unrefined_sections + panel_indices = findall(==(i), wing.refined_panel_mapping) + center_panel_idx = panel_indices[div(length(panel_indices), 2) + 1] + # Smoothing may shift values slightly, use absolute tolerance for small angles + @test wing.delta_dist[center_panel_idx] ≈ delta_input[i] atol=deg2rad(2.0) + end + end end From cbbc31162ba985c05fd5fdaac4ecb99c5f50ae8f Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sun, 7 Dec 2025 20:03:53 +0100 Subject: [PATCH 45/86] Add everything plotting function --- ext/VortexStepMethodControlPlotsExt.jl | 92 +++++++++++++++++++++++++- ext/VortexStepMethodMakieExt.jl | 14 +++- 2 files changed, 103 insertions(+), 3 deletions(-) diff --git a/ext/VortexStepMethodControlPlotsExt.jl b/ext/VortexStepMethodControlPlotsExt.jl index b2d09e9f..bbf985c7 100644 --- a/ext/VortexStepMethodControlPlotsExt.jl +++ b/ext/VortexStepMethodControlPlotsExt.jl @@ -3,7 +3,8 @@ using ControlPlots, LaTeXStrings, VortexStepMethod, LinearAlgebra, Statistics, D import ControlPlots: plt import VortexStepMethod: calculate_filaments_for_plotting -export plot_wing, plot_circulation_distribution, plot_geometry, plot_distribution, plot_polars, save_plot, show_plot, plot_polar_data +export plot_wing, plot_circulation_distribution, plot_geometry, plot_distribution, + plot_polars, save_plot, show_plot, plot_polar_data, plot_combined_analysis """ set_plot_style(titel_size=16; use_tex=false) @@ -925,4 +926,93 @@ function VortexStepMethod.plot_polar_data(body_aero::BodyAerodynamics; end end +""" + plot_combined_analysis(solver, body_aero, results; kwargs...) + +Create combined analysis by calling plot_geometry, plot_distribution, +and plot_polars sequentially. Each creates a separate matplotlib window. + +# Arguments +- `solver`: Solver or array of solvers +- `body_aero`: BodyAerodynamics object or array +- `results`: Results dict or array of results dicts + +See individual functions for detailed parameter descriptions. +""" +function VortexStepMethod.plot_combined_analysis( + solver, + body_aero, + results; + solver_label="VSM", + angle_range=range(0, 20, length=20), + angle_type="angle_of_attack", + angle_of_attack=0.0, + side_slip=0.0, + v_a=10.0, + title="Combined Analysis", + data_type=".pdf", + save_path=nothing, + is_save=false, + is_show=true, + view_elevation=15, + view_azimuth=-120, + use_tex=false, + literature_path_list=String[] +) + # Normalize inputs to arrays for consistent handling + solvers = solver isa Vector ? solver : [solver] + body_aeros = body_aero isa Vector ? body_aero : [body_aero] + results_list = results isa Vector ? results : [results] + labels = solver_label isa Vector ? solver_label : [solver_label] + + # Extract y-coordinates for distribution plot (use first body_aero) + body_y_coordinates = [panel.aero_center[2] for panel in body_aeros[1].panels] + y_coords_list = [body_y_coordinates for _ in 1:length(solvers)] + + # Plot geometry (only use first body_aero) + plot_geometry( + body_aeros[1], + title; + data_type=data_type, + save_path=save_path, + is_save=is_save, + is_show=is_show, + view_elevation=view_elevation, + view_azimuth=view_azimuth, + use_tex=use_tex + ) + + # Plot spanwise distributions + plot_distribution( + y_coords_list, + results_list, + labels; + title=title * " - Distributions", + data_type=data_type, + save_path=save_path, + is_save=is_save, + is_show=is_show, + use_tex=use_tex + ) + + # Plot polars + plot_polars( + solvers, + body_aeros, + labels; + literature_path_list=literature_path_list, + angle_range=angle_range, + angle_type=angle_type, + angle_of_attack=angle_of_attack, + side_slip=side_slip, + v_a=v_a, + title=title * " - Polars", + data_type=data_type, + save_path=save_path, + is_save=is_save, + is_show=is_show, + use_tex=use_tex + ) +end + end \ No newline at end of file diff --git a/ext/VortexStepMethodMakieExt.jl b/ext/VortexStepMethodMakieExt.jl index badf35c2..0ec5e5b5 100644 --- a/ext/VortexStepMethodMakieExt.jl +++ b/ext/VortexStepMethodMakieExt.jl @@ -929,7 +929,9 @@ end angle_of_attack=0.0, side_slip=0.0, v_a=10.0, title="Combined Analysis", view_elevation=15, view_azimuth=-120, - is_show=true, use_tex=false) + is_show=true, use_tex=false, + literature_path_list=String[], + data_type=".png", save_path=nothing, is_save=false) Create combined multi-panel figure with geometry, polar data, distributions, and polars. @@ -950,6 +952,10 @@ Create combined multi-panel figure with geometry, polar data, distributions, and - `view_azimuth`: Geometry view azimuth [°] (default: -120) - `is_show`: Display figure (default: true) - `use_tex`: Ignored for Makie (default: false) +- `literature_path_list`: Paths to literature CSV files (default: String[]) +- `data_type`: File extension (default: ".png", also supports ".jpeg") +- `save_path`: Directory path to save files (default: nothing) +- `is_save`: Save plots to files (default: false) """ function VortexStepMethod.plot_combined_analysis( solver, @@ -965,7 +971,11 @@ function VortexStepMethod.plot_combined_analysis( view_elevation=15, view_azimuth=-120, is_show=true, - use_tex=false + use_tex=false, + literature_path_list=String[], + data_type=".png", + save_path=nothing, + is_save=false ) # Auto-detect screen size and use 80% of it fig = try From 66ac77da825212e7526745df3d05361f2fed8bdf Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sun, 7 Dec 2025 20:06:58 +0100 Subject: [PATCH 46/86] Manual refine --- src/VortexStepMethod.jl | 10 ++-- src/body_aerodynamics.jl | 47 +++++++-------- src/obj_geometry.jl | 22 ++++--- src/precompile.jl | 1 + src/wing_geometry.jl | 120 ++++++++++++++++++++++++++------------- src/yaml_geometry.jl | 11 ++-- 6 files changed, 126 insertions(+), 85 deletions(-) diff --git a/src/VortexStepMethod.jl b/src/VortexStepMethod.jl index e4c730cd..9a3c7462 100644 --- a/src/VortexStepMethod.jl +++ b/src/VortexStepMethod.jl @@ -27,7 +27,7 @@ using Xfoil # Export public interface export VSMSettings, WingSettings, SolverSettings -export Wing, Section, ObjWing, reinit! +export Wing, Section, ObjWing, reinit!, refine! export BodyAerodynamics export Solver, solve, solve_base!, solve!, VSMSolution, linearize export calculate_results @@ -36,7 +36,7 @@ export calculate_span, calculate_projected_area export MVec3 export Model, VSM, LLT export AeroModel, LEI_AIRFOIL_BREUKELS, POLAR_VECTORS, POLAR_MATRICES, INVISCID -export PanelDistribution, LINEAR, COSINE, COSINE_VAN_GARREL, SPLIT_PROVIDED, UNCHANGED, NONE +export PanelDistribution, LINEAR, COSINE, COSINE_VAN_GARREL, SPLIT_PROVIDED, UNCHANGED export InitialGammaDistribution, ELLIPTIC, ZEROS export SolverStatus, FEASIBLE, INFEASIBLE, FAILURE export SolverType, LOOP, NONLIN @@ -130,16 +130,14 @@ Enumeration of the implemented panel distributions. - COSINE # Cosine distribution - `COSINE_VAN_GARREL` # van Garrel cosine distribution - `SPLIT_PROVIDED` # Split provided sections -- `UNCHANGED` # Keep original sections without interpolation -- `NONE` # No refinement - sections already refined +- `UNCHANGED` # 1:1 copy of unrefined to refined sections (no interpolation) """ @enum PanelDistribution begin LINEAR # Linear distribution COSINE # Cosine distribution COSINE_VAN_GARREL # van Garrel cosine distribution SPLIT_PROVIDED # Split provided sections - UNCHANGED # Keep original sections without interpolation - NONE # No refinement - sections already refined + UNCHANGED # 1:1 copy of unrefined to refined sections end """ diff --git a/src/body_aerodynamics.jl b/src/body_aerodynamics.jl index 1ca1506f..b40be910 100644 --- a/src/body_aerodynamics.jl +++ b/src/body_aerodynamics.jl @@ -71,6 +71,27 @@ function BodyAerodynamics( va=[15.0, 0.0, 0.0], omega=zeros(MVec3) ) where T <: AbstractWing + # Validate all wings are refined + for (i, wing) in enumerate(wings) + if isempty(wing.refined_sections) || + length(wing.refined_sections) != wing.n_panels + 1 + throw(ArgumentError( + "Wing $i has not been refined. " * + "Call refine!(wing) before creating BodyAerodynamics.\n\n" * + "Expected workflow:\n" * + " wing = Wing(...)\n" * + " refine!(wing)\n" * + " body_aero = BodyAerodynamics([wing])" + )) + end + + if isempty(wing.non_deformed_sections) + @warn "Wing $i has no non_deformed_sections. " * + "Deformation (unrefined_deform!) will not work. " * + "This should have been created by refine!." maxlog=1 + end + end + # Initialize panels panels = Panel[] n_unrefined_total = 0 @@ -79,17 +100,6 @@ function BodyAerodynamics( section.LE_point .-= kite_body_origin section.TE_point .-= kite_body_origin end - if wing.spanwise_distribution == NONE - # NONE distribution: refined_sections already populated in constructor - !(wing.n_panels == length(wing.refined_sections) - 1) && - throw(ArgumentError("(wing.n_panels = $(wing.n_panels)) != (length(wing.refined_sections) - 1 = $(length(wing.unrefined_sections) - 1))")) - elseif wing.spanwise_distribution == UNCHANGED - wing.refined_sections = wing.unrefined_sections - !(wing.n_panels == length(wing.unrefined_sections) - 1) && - throw(ArgumentError("(wing.n_panels = $(wing.n_panels)) != (length(wing.unrefined_sections) - 1 = $(length(wing.unrefined_sections) - 1))")) - else - wing.refined_sections = Section[Section() for _ in 1:wing.n_panels+1] - end # Create panels for _ in 1:wing.n_panels @@ -127,15 +137,9 @@ Initialize a BodyAerodynamics struct in-place by setting up panels and coefficie - `body_aero::BodyAerodynamics`: The structure to initialize # Keyword Arguments -- `init_aero::Bool`: Wether to initialize the aero data or not +- `init_aero::Bool`: Whether to initialize the aero data or not - `va=[15.0, 0.0, 0.0]`: Apparent wind vector - `omega=zeros(3)`: Turn rate in kite body frame x y and z -- `refine_mesh=true`: Whether to refine wing meshes. Set to `false` after - `deform!()` to preserve deformed geometry. -- `recompute_mapping=true`: Whether to recompute the refined panel mapping. - Set to `false` to skip mapping computation when it hasn't changed. -- `sort_sections=true`: Whether to sort sections by spanwise position. - Set to `false` for REFINE wings where section order is determined by structural connectivity. # Returns nothing @@ -143,15 +147,12 @@ nothing function reinit!(body_aero::BodyAerodynamics; init_aero=true, va=[15.0, 0.0, 0.0], - omega=zeros(MVec3), - refine_mesh=true, - recompute_mapping=true, - sort_sections=true + omega=zeros(MVec3) ) idx = 1 vec = @MVector zeros(3) for wing in body_aero.wings - reinit!(wing; refine_mesh, recompute_mapping, sort_sections) + reinit!(wing) panel_props = wing.panel_props # Create panels diff --git a/src/obj_geometry.jl b/src/obj_geometry.jl index b89874e5..bd0a56e6 100644 --- a/src/obj_geometry.jl +++ b/src/obj_geometry.jl @@ -428,15 +428,9 @@ function ObjWing( interp_steps=n_panels+1 ) - # Force NONE distribution for ObjWing - if spanwise_distribution != NONE - @warn "ObjWing only supports spanwise_distribution=NONE. Overriding to NONE." maxlog=1 - spanwise_distribution = NONE - end - # Set default: evenly spaced unrefined sections including both tips if isnothing(n_unrefined_sections) - # Default to having same number of unrefined sections as refined (no refinement) + # Default to having same number of unrefined sections as refined (no interpolation needed) n_unrefined_sections = n_panels + 1 end @@ -493,6 +487,7 @@ function ObjWing( push!(sections, Section(LE_point, TE_point, POLAR_MATRICES, aero_data)) end + # Create refined sections (evenly spaced including both tips) refined_sections = Section[] for gamma in range(-gamma_tip, gamma_tip, n_panels+1) LE_point = [le_interp[i](gamma) for i in 1:3] @@ -500,17 +495,26 @@ function ObjWing( push!(refined_sections, Section(LE_point, TE_point, POLAR_MATRICES, aero_data)) end + # Create non_deformed_sections as copy of refined_sections for deformation support + non_deformed_sections = [Section() for _ in 1:n_panels+1] + for i in 1:n_panels+1 + reinit!(non_deformed_sections[i], refined_sections[i]) + end + panel_props = PanelProperties{n_panels}() cache = [PreallocationTools.LazyBufferCache()] wing = Wing(n_panels, Int16(n_unrefined_sections), spanwise_distribution, panel_props, MVec3(spanwise_direction), sections, refined_sections, remove_nan, Int16[], - Section[], zeros(n_panels), zeros(n_panels), + non_deformed_sections, zeros(n_panels), zeros(n_panels), mass, gamma_tip, inertia_tensor, T_cad_body, R_cad_body, radius, le_interp, te_interp, area_interp, cache) - # Refine mesh and update panel properties + # Compute panel mapping for deformation support + VortexStepMethod.compute_refined_panel_mapping!(wing) + + # Update panel properties reinit!(wing) wing diff --git a/src/precompile.jl b/src/precompile.jl index cd9a44ab..aefd41f6 100644 --- a/src/precompile.jl +++ b/src/precompile.jl @@ -26,6 +26,7 @@ INVISCID) # Step 3: Initialize aerodynamics (simplified) + refine!(wing) body_aero = BodyAerodynamics([wing]) nothing diff --git a/src/wing_geometry.jl b/src/wing_geometry.jl index 3a11fb08..5f2acfa4 100644 --- a/src/wing_geometry.jl +++ b/src/wing_geometry.jl @@ -297,25 +297,20 @@ function Wing(n_panels::Int; end """ - reinit!(wing::AbstractWing; refine_mesh=true, recompute_mapping=true, sort_sections=true) + reinit!(wing::AbstractWing) -Reinitialize wing geometry and panel properties. +Reinitialize wing panel properties based on current refined_sections geometry. -# Keyword Arguments -- `refine_mesh::Bool=true`: Whether to refine the mesh. Set to `false` after - `deform!()` to preserve deformed geometry while updating panel properties. -- `recompute_mapping::Bool=true`: Whether to recompute the refined panel mapping. - Set to `false` to skip mapping computation when it hasn't changed. -- `sort_sections::Bool=true`: Whether to sort sections by spanwise position. - Set to `false` for REFINE wings where section order is determined by structural connectivity. -""" -function reinit!(wing::AbstractWing; refine_mesh=true, recompute_mapping=true, sort_sections=true) - # Refine mesh unless explicitly disabled (e.g., to preserve deformation) - if refine_mesh - refine_aerodynamic_mesh!(wing; recompute_mapping, sort_sections) - end +This function only updates panel properties (chord, area, etc.) from the existing +refined_sections. It does NOT refine the mesh - call refine_aerodynamic_mesh!(wing) +first if needed. - # Calculate panel properties +# Note +After deformation via `unrefined_deform!()` or `deform!()`, call `reinit!` to update +panel properties while preserving the deformed geometry. +""" +function reinit!(wing::AbstractWing) + # Calculate panel properties from refined sections update_panel_properties!( wing.panel_props, wing.refined_sections, @@ -620,54 +615,99 @@ end Create non_deformed_sections to match refined_sections. This enables deformation support for all wings (YAML and OBJ). -Should be called after refined_sections are populated for the FIRST time only. +Should be called after refined_sections are populated. Once populated, non_deformed_sections serves as the undeformed reference geometry. """ function update_non_deformed_sections!(wing::AbstractWing) n_sections = wing.n_panels + 1 - # Only populate non_deformed_sections if it's empty (initial setup) - # Once populated, it serves as the undeformed reference and should not be overwritten + # Populate or update non_deformed_sections if isempty(wing.non_deformed_sections) + @show length(wing.refined_sections) n_sections + # Initial setup wing.non_deformed_sections = [Section() for _ in 1:n_sections] for i in 1:n_sections reinit!(wing.non_deformed_sections[i], wing.refined_sections[i]) end + elseif length(wing.non_deformed_sections) != n_sections + # Size mismatch - error + throw(ArgumentError( + "non_deformed_sections has incorrect size. " * + "Expected $(n_sections) sections (n_panels+1), got $(length(wing.non_deformed_sections)). " * + "This indicates an inconsistent wing state." + )) + else + # Correct size - update all sections + for i in 1:n_sections + reinit!(wing.non_deformed_sections[i], wing.refined_sections[i]) + end end return nothing end """ - refine_aerodynamic_mesh!(wing::AbstractWing; recompute_mapping=true, sort_sections=true) - -Refine the aerodynamic mesh of the wing based on spanwise panel distribution. + refine!(wing::AbstractWing; recompute_mapping=true, sort_sections=true) + +Refine the wing aerodynamic mesh from unrefined sections to refined sections. + +This function interpolates the wing geometry from a coarse set of unrefined sections +to a fine mesh of refined sections (n_panels+1 sections) based on the wing's +spanwise_distribution setting. It also populates non_deformed_sections which +enables deformation support via `unrefined_deform!`. + +# Required Workflow +Must be called after wing construction and before creating `BodyAerodynamics`: +```julia +wing = Wing("wing.yaml"; n_panels=40) # or ObjWing(...) or manual Wing +refine!(wing) # Refine mesh +body_aero = BodyAerodynamics([wing]) # Create aerodynamics +``` + +# Distribution Methods +- `LINEAR`: Linear interpolation between sections +- `COSINE`: Cosine spacing (more panels near tips) +- `COSINE_VAN_GARREL`: van Garrel cosine distribution +- `SPLIT_PROVIDED`: Split each unrefined section into sub-panels +- `UNCHANGED`: 1:1 copy when n_unrefined_sections == n_panels+1 # Keyword Arguments -- `recompute_mapping::Bool=true`: Whether to recompute the refined panel mapping. - Set to `false` to skip mapping computation when it hasn't changed. -- `sort_sections::Bool=true`: Whether to sort sections by spanwise position (y-coordinate). - Set to `false` for REFINE wings where section order is determined by structural connectivity. +- `recompute_mapping::Bool=true`: Recompute the mapping from refined panels to unrefined sections +- `sort_sections::Bool=true`: Sort sections by spanwise position (disable for structural ordering) -Returns: - Vector{Section}: List of refined sections +# Effects +1. Populates `wing.refined_sections` (n_panels+1 sections) +2. Populates `wing.non_deformed_sections` (copy of refined_sections for deformation reference) +3. Computes `wing.refined_panel_mapping` (panel → unrefined section mapping) +4. Resizes `wing.theta_dist` and `wing.delta_dist` to n_panels + +# Example +```julia +# YAML wing +wing = Wing("wing.yaml"; n_panels=40) +refine!(wing) +body_aero = BodyAerodynamics([wing]) + +# After refinement, deformation is supported +unrefined_deform!(wing, theta_angles, delta_angles) +``` """ -function refine_aerodynamic_mesh!(wing::AbstractWing; recompute_mapping=true, sort_sections=true) +function refine!(wing::AbstractWing; recompute_mapping=true, sort_sections=true) + # Validate unrefined_sections exist + if isempty(wing.unrefined_sections) + throw(ArgumentError( + "Cannot refine mesh: wing has no unrefined_sections. " * + "Add sections using add_section! or check wing construction." + )) + end + # Only sort sections if requested (skip for REFINE wings with fixed structural order) sort_sections && sort!(wing.unrefined_sections, by=s -> s.LE_point[2], rev=true) n_sections = wing.n_panels + 1 - # Handle NONE distribution - sections already refined, just compute mapping - if wing.spanwise_distribution == NONE - if length(wing.refined_sections) != n_sections - throw(ArgumentError("NONE distribution requires refined_sections to be pre-populated")) - end - recompute_mapping && compute_refined_panel_mapping!(wing) - update_non_deformed_sections!(wing) - return nothing - end - if length(wing.refined_sections) == 0 - if wing.spanwise_distribution == UNCHANGED || length(wing.unrefined_sections) == n_sections + @show wing.spanwise_distribution + if wing.spanwise_distribution == UNCHANGED || + length(wing.unrefined_sections) == n_sections wing.refined_sections = wing.unrefined_sections update_non_deformed_sections!(wing) return nothing diff --git a/src/yaml_geometry.jl b/src/yaml_geometry.jl index 60571026..4df42382 100644 --- a/src/yaml_geometry.jl +++ b/src/yaml_geometry.jl @@ -246,7 +246,7 @@ function Wing( # Get coordinates directly from struct fields le_coord = [section.LE_x, section.LE_y, section.LE_z] te_coord = [section.TE_x, section.TE_y, section.TE_z] - + # Load polar data and create section csv_file_path = get(airfoil_csv_map, section.airfoil_id, "") if !isempty(csv_file_path) && !isabspath(csv_file_path) @@ -256,15 +256,12 @@ function Wing( csv_file_path = joinpath(dirname(geometry_file), csv_file_path) end aero_data, aero_model = load_polar_data(csv_file_path) - + prn && println("Section airfoil_id $(section.airfoil_id): Using $aero_model model") - + add_section!(wing, le_coord, te_coord, aero_model, aero_data) end - - # Initialize the wing after adding all sections - reinit!(wing) - + return wing end From ec46e3bc4f22e2d7b3b08cf8a548b0586d067c35 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sun, 7 Dec 2025 20:34:15 +0100 Subject: [PATCH 47/86] Improved makie plotting --- ext/VortexStepMethodMakieExt.jl | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/ext/VortexStepMethodMakieExt.jl b/ext/VortexStepMethodMakieExt.jl index 0ec5e5b5..62d5343c 100644 --- a/ext/VortexStepMethodMakieExt.jl +++ b/ext/VortexStepMethodMakieExt.jl @@ -1037,7 +1037,7 @@ function VortexStepMethod.plot_combined_analysis( set_axes_equal_makie!(ax_geo, panels; zoom=0.5) axislegend(ax_geo; position=:lt) - # [1,2] Polar Data Surfaces + # [1,2] Polar Data Surfaces or Curves if body_aero.panels[1].aero_model == POLAR_MATRICES alphas = collect(deg2rad.(-5:0.3:25)) delta_tes = collect(deg2rad.(-5:0.3:25)) @@ -1062,6 +1062,30 @@ function VortexStepMethod.plot_combined_analysis( wireframe!(ax, delta_tes, alphas, interp_matrix; color=:blue, linewidth=0.5, transparency=true) end + elseif body_aero.panels[1].aero_model == POLAR_VECTORS + alphas_deg = collect(-5:0.5:25) + alphas = deg2rad.(alphas_deg) + + ax_cl_curve = Axis(fig[1, 2][1, 1]; + title="Cl vs α", + xlabel="α [°]", + ylabel="Cl") + ax_cd_curve = Axis(fig[1, 2][1, 2]; + title="Cd vs α", + xlabel="α [°]", + ylabel="Cd") + ax_cm_curve = Axis(fig[1, 2][1, 3]; + title="Cm vs α", + xlabel="α [°]", + ylabel="Cm") + + cl_vals = [body_aero.panels[1].cl_interp(a) for a in alphas] + cd_vals = [body_aero.panels[1].cd_interp(a) for a in alphas] + cm_vals = [body_aero.panels[1].cm_interp(a) for a in alphas] + + lines!(ax_cl_curve, alphas_deg, cl_vals; color=:blue, linewidth=2) + lines!(ax_cd_curve, alphas_deg, cd_vals; color=:red, linewidth=2) + lines!(ax_cm_curve, alphas_deg, cm_vals; color=:green, linewidth=2) end # [2,1] Spanwise Distributions (3×3 grid) @@ -1158,6 +1182,10 @@ function VortexStepMethod.plot_combined_analysis( label=label_with_re, marker=:star5, markersize=12) axislegend(ax_polar, position=:lt) + # Set column widths: left column wider for 3x3 grid + colsize!(fig.layout, 1, Relative(0.6)) + colsize!(fig.layout, 2, Relative(0.4)) + if is_show display(fig) end From 9e535dab4775f4c93bb972ba10b3fb58a1a0af80 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sun, 7 Dec 2025 20:34:29 +0100 Subject: [PATCH 48/86] Deformable yaml kite --- examples/V3_kite.jl | 69 +++++++++++++++--------------------- examples/pyramid_model.jl | 44 +++++------------------ examples/rectangular_wing.jl | 45 ++++++++--------------- examples/stall_model.jl | 53 ++++++--------------------- 4 files changed, 61 insertions(+), 150 deletions(-) diff --git a/examples/V3_kite.jl b/examples/V3_kite.jl index 560fd98d..9dafd212 100644 --- a/examples/V3_kite.jl +++ b/examples/V3_kite.jl @@ -2,6 +2,10 @@ using LinearAlgebra using VortexStepMethod using GLMakie +PLOT = true +USE_TEX = false +DEFORM = false + project_dir = dirname(dirname(pathof(VortexStepMethod))) # Go up one level from src to project root# literature_paths = [ joinpath(project_dir, "data", "TUDELFT_V3_KITE", "literature_results","CFD_RANS_Rey_5e5_Poland2025_alpha_sweep_beta_0_NoStruts.csv"), @@ -11,8 +15,8 @@ literature_paths = [ ] labels= [ "Julia VSM 2D CFD PCHIP", - "CFD RANS Re=5e5", - "CFD RANS Re=10e5 (With Struts)", + "CFD RANS Re=5e5", + "CFD RANS Re=10e5 (With Struts)", "Python VSM 2D CFD PCHIP Re=5e5", "Wind Tunnel Re=5e5 (With Struts)" ] @@ -22,7 +26,20 @@ settings = VSMSettings("TUDELFT_V3_KITE/vsm_settings.yaml") # Create wing, body_aero, and solver objects using settings wing = Wing(settings) +refine!(wing) body_aero = BodyAerodynamics([wing]) +VortexStepMethod.reinit!(body_aero) + +if DEFORM + VortexStepMethod.unrefined_deform!( + wing, + deg2rad.(range(-10, 10, length=wing.n_unrefined_sections)), + deg2rad.(range(0, 0, length=wing.n_unrefined_sections)); + smooth=true + ) + VortexStepMethod.reinit!(body_aero; init_aero=false) +end + solver = Solver(body_aero, settings) # Set flight conditions from settings @@ -38,53 +55,23 @@ yaw_rate = settings.condition.yaw_rate PLOT = true USE_TEX = false -# Plotting polars -PLOT && plot_polars( - [solver], - [body_aero], - labels, +# Solve and plot combined analysis +results = VortexStepMethod.solve(solver, body_aero; log=true) +PLOT && plot_combined_analysis( + solver, + body_aero, + results; + solver_label="VSM", literature_path_list=literature_paths, angle_range=range(-5, 25, length=30), angle_type="angle_of_attack", angle_of_attack=angle_of_attack_deg, side_slip=sideslip_deg, v_a=wind_speed, - title="$(wing.n_panels)_panels_$(wing.spanwise_distribution)_from_yaml_settings", - data_type=".png", - is_save=false, - is_show=true, - use_tex=USE_TEX -) - - -# Plotting geometry -results = VortexStepMethod.solve(solver, body_aero; log=true) -PLOT && plot_geometry( - body_aero, - ""; - data_type=".svg", - save_path="", - is_save=false, - is_show=true, - view_elevation=15, - view_azimuth=-120, - use_tex=USE_TEX -) - - -# Plotting spanwise distributions -body_y_coordinates = [panel.aero_center[2] for panel in body_aero.panels] - -PLOT && plot_distribution( - [body_y_coordinates], - [results], - ["VSM"]; - title="CAD_spanwise_distributions_alpha_$(round(angle_of_attack_deg, digits=1))_delta_$(round(sideslip_deg, digits=1))_yaw_$(round(yaw_rate, digits=1))_v_a_$(round(wind_speed, digits=1))", - data_type=".png", - is_save=false, + title="TU Delft V3 Kite", is_show=true, use_tex=USE_TEX ) -nothing \ No newline at end of file +nothing diff --git a/examples/pyramid_model.jl b/examples/pyramid_model.jl index 43d4220a..bc2f0d2a 100644 --- a/examples/pyramid_model.jl +++ b/examples/pyramid_model.jl @@ -9,6 +9,7 @@ vsm_settings = VSMSettings("pyramid_model/vsm_settings.yaml") # Create wing, body_aero, and solver objects using vsm_settings wing = Wing(vsm_settings) +refine!(wing) body_aero = BodyAerodynamics([wing]) solver = Solver(body_aero, vsm_settings) @@ -28,47 +29,18 @@ results = VortexStepMethod.solve(solver, body_aero; log=true) PLOT = true USE_TEX = false -# Plotting polars -PLOT && plot_polars( - [solver], - [body_aero], - ["VSM Pyramid Model"], +# Plotting combined analysis +PLOT && plot_combined_analysis( + solver, + body_aero, + results; + solver_label="VSM", angle_range=range(-5, 25, length=30), angle_type="angle_of_attack", angle_of_attack=angle_of_attack_deg, side_slip=sideslip_deg, v_a=wind_speed, - title="$(wing.n_panels)_panels_$(wing.spanwise_distribution)_pyramid_model", - data_type=".png", - is_save=false, - is_show=true, - use_tex=USE_TEX -) - -# Plotting geometry -results = VortexStepMethod.solve(solver, body_aero; log=true) -PLOT && plot_geometry( - body_aero, - ""; - data_type=".svg", - save_path="", - is_save=false, - is_show=true, - view_elevation=15, - view_azimuth=-120, - use_tex=USE_TEX -) - -# Plotting spanwise distributions -body_y_coordinates = [panel.aero_center[2] for panel in body_aero.panels] - -PLOT && plot_distribution( - [body_y_coordinates], - [results], - ["VSM"]; - title="pyramid_spanwise_distributions_alpha_$(round(angle_of_attack_deg, digits=1))_delta_$(round(sideslip_deg, digits=1))_yaw_$(round(yaw_rate, digits=1))_v_a_$(round(wind_speed, digits=1))", - data_type=".png", - is_save=false, + title="Pyramid Model", is_show=true, use_tex=USE_TEX ) diff --git a/examples/rectangular_wing.jl b/examples/rectangular_wing.jl index 330de483..7053337d 100644 --- a/examples/rectangular_wing.jl +++ b/examples/rectangular_wing.jl @@ -18,15 +18,18 @@ alpha = deg2rad(alpha_deg) wing = Wing(n_panels, spanwise_distribution=LINEAR) # Add wing sections - defining only tip sections with inviscid airfoil model -add_section!(wing, - [0.0, span/2, 0.0], # Left tip LE +add_section!(wing, + [0.0, span/2, 0.0], # Left tip LE [chord, span/2, 0.0], # Left tip TE INVISCID) -add_section!(wing, +add_section!(wing, [0.0, -span/2, 0.0], # Right tip LE [chord, -span/2, 0.0], # Right tip TE INVISCID) +# Refine mesh +refine!(wing) + # Step 3: Initialize aerodynamics body_aero = BodyAerodynamics([wing]) @@ -53,38 +56,18 @@ println("CL = $(round(results_vsm["cl"], digits=4))") println("CD = $(round(results_vsm["cd"], digits=4))") println("Projected area = $(round(results_vsm["projected_area"], digits=4)) m²") -# Step 6: Plot geometry -PLOT && plot_geometry( - body_aero, - "Rectangular_wing_geometry"; - data_type=".png", - save_path=".", - is_save=false, - is_show=true, - use_tex=USE_TEX -) - -# Step 7: Plot spanwise distributions -y_coordinates = [panel.aero_center[2] for panel in body_aero.panels] - -PLOT && plot_distribution( - [y_coordinates, y_coordinates], - [results_vsm, results_llt], - ["VSM", "LLT"], - title="Spanwise Distributions", - use_tex=USE_TEX -) - -# Step 8: Plot polar curves +# Step 6: Plot combined analysis angle_range = range(0, 20, 20) -PLOT && plot_polars( +PLOT && plot_combined_analysis( [llt_solver, vsm_solver], [body_aero, body_aero], - ["LLT", "VSM"]; - angle_range, + [results_llt, results_vsm]; + solver_label=["LLT", "VSM"], + angle_range=angle_range, angle_type="angle_of_attack", - v_a, - title="Rectangular Wing Polars", + v_a=v_a, + title="Rectangular Wing", + is_show=true, use_tex=USE_TEX ) nothing diff --git a/examples/stall_model.jl b/examples/stall_model.jl index b6d01e92..fe83e718 100644 --- a/examples/stall_model.jl +++ b/examples/stall_model.jl @@ -39,6 +39,7 @@ CAD_wing = Wing(n_panels; spanwise_distribution) for rib in rib_list add_section!(CAD_wing, rib[1], rib[2], rib[3], rib[4]) end +refine!(CAD_wing) body_aero = BodyAerodynamics([CAD_wing]) # Create solvers @@ -64,40 +65,12 @@ vel_app = [ ] * v_a set_va!(body_aero, vel_app) -# Plotting geometry -PLOT && plot_geometry( - body_aero, - ""; - data_type=".svg", - save_path="", - is_save=false, - is_show=true, - view_elevation=15, - view_azimuth=-120, - use_tex=USE_TEX -) - -# Solving and plotting distributions +# Solve both configurations results = solve(vsm_solver, body_aero) @time results_with_stall = solve(VSM_with_stall_correction, body_aero) @time results_with_stall = solve(VSM_with_stall_correction, body_aero) -CAD_y_coordinates = [panel.aero_center[2] for panel in body_aero.panels] - -PLOT && plot_distribution( - [CAD_y_coordinates, CAD_y_coordinates], - [results, results_with_stall], - ["VSM", "VSM with stall correction"]; - title="CAD_spanwise_distributions_alpha_$(round(aoa, digits=1))_delta_$(round(side_slip, digits=1))_yaw_$(round(yaw_rate, digits=1))_v_a_$(round(v_a, digits=1))", - data_type=".png", - save_path=joinpath(save_folder, "spanwise_distributions"), - is_save=false, - is_show=true, - use_tex=USE_TEX -) - -# Plotting polar -save_path = joinpath(root_dir, "results", "TUD_V3_LEI_KITE") +# Setup literature data paths path_cfd_lebesque = joinpath( root_dir, "data", @@ -108,24 +81,20 @@ path_cfd_lebesque = joinpath( # Only include literature data if file exists literature_paths = isfile(path_cfd_lebesque) ? [path_cfd_lebesque] : String[] -labels = isfile(path_cfd_lebesque) ? - ["VSM CAD 19ribs", "VSM CAD 19ribs , with stall correction", "CFD_Lebesque Rey 30e5"] : - ["VSM CAD 19ribs", "VSM CAD 19ribs , with stall correction"] -PLOT && plot_polars( +# Plot combined analysis +PLOT && plot_combined_analysis( [vsm_solver, VSM_with_stall_correction], [body_aero, body_aero], - labels; + [results, results_with_stall]; + solver_label=["VSM", "VSM (with stall)"], literature_path_list=literature_paths, angle_range=range(0, 25, length=25), angle_type="angle_of_attack", - angle_of_attack=0, - side_slip=0, - v_a=10, - title="tutorial_testing_stall_model_n_panels_$(n_panels)_distribution_$(spanwise_distribution)_unrefined_$(CAD_wing.n_unrefined_sections)", - data_type=".png", - save_path=joinpath(save_folder, "polars"), - is_save=true, + angle_of_attack=aoa, + side_slip=side_slip, + v_a=v_a, + title="Stall Model Comparison", is_show=true, use_tex=USE_TEX ) From 56f219ec18992dd06b8fb024b673cadd3f3313da Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sun, 7 Dec 2025 21:29:44 +0100 Subject: [PATCH 49/86] Fix for updated separate refine --- test/bench.jl | 8 +++-- test/bench_solve.jl | 4 ++- .../test_body_aerodynamics.jl | 15 ++++++++-- test/plotting/test_plotting.jl | 2 ++ test/ram_geometry/test_kite_geometry.jl | 4 +-- test/runtests.jl | 1 + test/solver/test_solver.jl | 4 ++- test/solver/test_unrefined_dist.jl | 8 +++-- test/wake/test_wake.jl | 1 + test/wing_geometry/test_wing_geometry.jl | 30 +++++++++---------- test/yaml_geometry/test_wing_constructor.jl | 10 ++----- .../test_yaml_wing_deformation.jl | 30 ++++++++++++------- 12 files changed, 72 insertions(+), 45 deletions(-) diff --git a/test/bench.jl b/test/bench.jl index b5d1ba27..42c256f4 100644 --- a/test/bench.jl +++ b/test/bench.jl @@ -51,10 +51,12 @@ const IS_JULIA_1_12_OR_NEWER = VERSION >= v"1.12" [chord, -span/2, 0.0], # Right tip TE INVISCID) + refine!(wing) body_aero = BodyAerodynamics([wing]) + refine!(unchanged_wing) unchanged_body_aero = BodyAerodynamics([unchanged_wing]) reinit!(unchanged_body_aero) - + @testset "Re-initialization" begin result = @benchmark reinit!($unchanged_body_aero; init_aero=false) samples=1 evals=1 @info "Re-initializing Allocations: $(result.allocs) \t Memory: $(result.memory)" @@ -136,7 +138,9 @@ const IS_JULIA_1_12_OR_NEWER = VERSION >= v"1.12" [chord, -span/2, 0.0], # Right tip TE aero_model, aero_data) - body_aero = BodyAerodynamics([wing]) + refine!(wing) + refine!(wing) + body_aero = BodyAerodynamics([wing]) solver = Solver(body_aero; aerodynamic_model_type=model diff --git a/test/bench_solve.jl b/test/bench_solve.jl index dc8c4590..1f3b934f 100644 --- a/test/bench_solve.jl +++ b/test/bench_solve.jl @@ -30,7 +30,9 @@ add_section!(wing, INVISCID) # Step 3: Initialize aerodynamics -wa = BodyAerodynamics([wing]) +wa = refine!(wing) + refine!(wing) + body_aero = BodyAerodynamics([wing]) # Set inflow conditions vel_app = [cos(alpha), 0.0, sin(alpha)] .* v_a diff --git a/test/body_aerodynamics/test_body_aerodynamics.jl b/test/body_aerodynamics/test_body_aerodynamics.jl index 6e61857c..c89415aa 100644 --- a/test/body_aerodynamics/test_body_aerodynamics.jl +++ b/test/body_aerodynamics/test_body_aerodynamics.jl @@ -37,6 +37,8 @@ include("../utils.jl") ) end + refine!(wing) + refine!(wing) body_aero = BodyAerodynamics([wing]) set_va!(body_aero, v_a) @@ -120,7 +122,8 @@ end add_section!(wing, [0.0, 0.0, 0.0], [1.0, 0.0, 0.0], INVISCID) add_section!(wing, [0.0, 1.0, 0.0], [1.0, 1.0, 0.0], INVISCID) add_section!(wing, [0.0, 2.0, 0.0], [1.0, 2.0, 0.0], INVISCID) - + refine!(wing) + # Test non-zero origin translation origin = MVec3(1.0, 2.0, 3.0) body_aero = BodyAerodynamics([wing]; kite_body_origin=origin) @@ -174,7 +177,9 @@ end INVISCID ) end - body_aero = BodyAerodynamics([wing]) + refine!(wing) + refine!(wing) + body_aero = BodyAerodynamics([wing]) set_va!(body_aero, v_a) return body_aero, coord, v_a, model @@ -304,6 +309,8 @@ end ) end + refine!(wing) + refine!(wing) body_aero = BodyAerodynamics([wing]) set_va!(body_aero, v_a) @@ -416,7 +423,9 @@ end try settings = VSMSettings(settings_file) wing = Wing(settings) - body_aero = BodyAerodynamics([wing]) + body_aero = refine!(wing) + refine!(wing) + body_aero = BodyAerodynamics([wing]) set_va!(body_aero, settings) diff --git a/test/plotting/test_plotting.jl b/test/plotting/test_plotting.jl index 0bcfc6cc..29fe4a20 100644 --- a/test/plotting/test_plotting.jl +++ b/test/plotting/test_plotting.jl @@ -56,6 +56,7 @@ function create_body_aero() INVISCID) # Step 3: Initialize aerodynamics + refine!(wing) body_aero = BodyAerodynamics([wing]) # Set inflow conditions vel_app = [cos(alpha), 0.0, sin(alpha)] .* v_a @@ -124,6 +125,7 @@ end safe_rm(joinpath(save_dir, "Rectangular_Wing_Polars.png")) # Step 9: Test polar data plotting + # ram_wing is an ObjWing - no refine! needed body_aero = BodyAerodynamics([ram_wing]) fig = plot_polar_data(body_aero; is_show=false) @test fig isa Figure diff --git a/test/ram_geometry/test_kite_geometry.jl b/test/ram_geometry/test_kite_geometry.jl index 894664d2..7df146dd 100644 --- a/test/ram_geometry/test_kite_geometry.jl +++ b/test/ram_geometry/test_kite_geometry.jl @@ -169,7 +169,7 @@ using Serialization wing = ObjWing(test_obj_path, test_dat_path; remove_nan=true) @test wing.n_panels == 56 # Default value - @test wing.spanwise_distribution == NONE + @test wing.spanwise_distribution == UNCHANGED @test wing.spanwise_direction ≈ [0.0, 1.0, 0.0] @test length(wing.unrefined_sections) > 0 # Should have sections now @test wing.mass ≈ 1.0 @@ -186,7 +186,7 @@ using Serialization end @testset "Wing Deformation" begin - # Create an ObjWing for testing + # Create an ObjWing for testing (no refine! needed - fully complete) wing = ObjWing(test_obj_path, test_dat_path; remove_nan=true) body_aero = BodyAerodynamics([wing]) diff --git a/test/runtests.jl b/test/runtests.jl index d0b770d4..593b9c81 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -37,6 +37,7 @@ end::Bool end should_run_test("body_aerodynamics/test_body_aerodynamics.jl") && include("body_aerodynamics/test_body_aerodynamics.jl") should_run_test("body_aerodynamics/test_results.jl") && include("body_aerodynamics/test_results.jl") + should_run_test("test_refinement_validation.jl") && include("test_refinement_validation.jl") should_run_test("filament/test_bound_filament.jl") && include("filament/test_bound_filament.jl") should_run_test("filament/test_semi_infinite_filament.jl") && include("filament/test_semi_infinite_filament.jl") should_run_test("panel/test_panel.jl") && include("panel/test_panel.jl") diff --git a/test/solver/test_solver.jl b/test/solver/test_solver.jl index 1d60061a..5004986b 100644 --- a/test/solver/test_solver.jl +++ b/test/solver/test_solver.jl @@ -11,7 +11,9 @@ using Test # Test Solver constructor with VSMSettings settings = VSMSettings(settings_file) wing = Wing(settings) - body_aero = BodyAerodynamics([wing]) + refine!(wing) + refine!(wing) + body_aero = BodyAerodynamics([wing]) solver = Solver(body_aero, settings) # Verify solver properties match settings diff --git a/test/solver/test_unrefined_dist.jl b/test/solver/test_unrefined_dist.jl index 219cc65e..5e2d131a 100644 --- a/test/solver/test_unrefined_dist.jl +++ b/test/solver/test_unrefined_dist.jl @@ -19,7 +19,9 @@ using Test # Create wing and solver wing = Wing(settings) - body_aero = BodyAerodynamics([wing]) + refine!(wing) + refine!(wing) + body_aero = BodyAerodynamics([wing]) solver = Solver(body_aero, settings) # Set conditions and solve @@ -96,7 +98,9 @@ using Test settings.solver_settings.n_panels = n_panels wing = Wing(settings) - body_aero = BodyAerodynamics([wing]) + refine!(wing) + refine!(wing) + body_aero = BodyAerodynamics([wing]) solver = Solver(body_aero, settings) va = [10.0, 0.0, 0.0] diff --git a/test/wake/test_wake.jl b/test/wake/test_wake.jl index b1c45f87..e6d604f5 100644 --- a/test/wake/test_wake.jl +++ b/test/wake/test_wake.jl @@ -20,6 +20,7 @@ using VortexStepMethod try # Create wing and body aerodynamics with known good geometry + # ObjWing is fully complete - no refine! needed wing = ObjWing(body_path, foil_path; n_panels=56) # Use default panels body_aero = BodyAerodynamics([wing]) diff --git a/test/wing_geometry/test_wing_geometry.jl b/test/wing_geometry/test_wing_geometry.jl index 8c4ba69c..74704048 100644 --- a/test/wing_geometry/test_wing_geometry.jl +++ b/test/wing_geometry/test_wing_geometry.jl @@ -1,7 +1,7 @@ using Test using LinearAlgebra using VortexStepMethod -using VortexStepMethod: Wing, Section, add_section!, refine_mesh_by_splitting_provided_sections!, refine_aerodynamic_mesh! +using VortexStepMethod: Wing, Section, add_section!, refine_mesh_by_splitting_provided_sections!, refine! import Base: == """ @@ -98,7 +98,7 @@ end add_section!(example_wing, [0.0, 1.0, 0.0], [0.0, 1.0, 0.0], INVISCID) add_section!(example_wing, [0.0, -1.0, 0.0], [0.0, -1.0, 0.0], INVISCID) add_section!(example_wing, [0.0, -1.5, 0.0], [0.0, -1.5, 0.0], INVISCID) - refine_aerodynamic_mesh!(example_wing) + refine!(example_wing) sections = example_wing.refined_sections # Test right to left order @@ -106,7 +106,7 @@ end add_section!(example_wing_1, [0.0, -1.5, 0.0], [0.0, -1.5, 0.0], INVISCID) add_section!(example_wing_1, [0.0, -1.0, 0.0], [0.0, -1.0, 0.0], INVISCID) add_section!(example_wing_1, [0.0, 1.0, 0.0], [0.0, 1.0, 0.0], INVISCID) - refine_aerodynamic_mesh!(example_wing_1) + refine!(example_wing_1) sections_1 = example_wing_1.refined_sections # Test random order @@ -114,7 +114,7 @@ end add_section!(example_wing_2, [0.0, 1.0, 0.0], [0.0, 1.0, 0.0], INVISCID) add_section!(example_wing_2, [0.0, -1.5, 0.0], [0.0, -1.5, 0.0], INVISCID) add_section!(example_wing_2, [0.0, -1.0, 0.0], [0.0, -1.0, 0.0], INVISCID) - refine_aerodynamic_mesh!(example_wing_2) + refine!(example_wing_2) sections_2 = example_wing_2.refined_sections for i in eachindex(sections) @@ -133,7 +133,7 @@ end wing = Wing(n_panels; spanwise_distribution=LINEAR) add_section!(wing, [0.0, span/2, 0.0], [-1.0, span/2, 0.0], INVISCID) add_section!(wing, [0.0, -span/2, 0.0], [-1.0, -span/2, 0.0], INVISCID) - refine_aerodynamic_mesh!(wing) + refine!(wing) sections = wing.refined_sections @test length(sections) == wing.n_panels + 1 @@ -149,7 +149,7 @@ end wing = Wing(n_panels; spanwise_distribution=COSINE) add_section!(wing, [0.0, span/2, 0.0], [-1.0, span/2, 0.0], INVISCID) add_section!(wing, [0.0, -span/2, 0.0], [-1.0, -span/2, 0.0], INVISCID) - refine_aerodynamic_mesh!(wing) + refine!(wing) sections = wing.refined_sections @test length(sections) == wing.n_panels + 1 @@ -173,7 +173,7 @@ end add_section!(wing, [0.0, span/2, 0.0], [-1.0, span/2, 0.0], INVISCID) add_section!(wing, [0.0, -span/2, 0.0], [-1.0, -span/2, 0.0], INVISCID) - refine_aerodynamic_mesh!(wing) + refine!(wing) sections = wing.unrefined_sections @test length(sections) == wing.n_panels + 1 @test sections[1].LE_point ≈ [0.0, span/2, 0.0] @@ -188,7 +188,7 @@ end add_section!(wing, [0.0, span/2, 0.0], [-1.0, span/2, 0.0], INVISCID) add_section!(wing, [0.0, -span/2, 0.0], [-1.0, -span/2, 0.0], INVISCID) - refine_aerodynamic_mesh!(wing) + refine!(wing) sections = wing.refined_sections @test length(sections) == wing.n_panels + 1 @test sections[1].LE_point ≈ [0.0, span/2, 0.0] @@ -206,7 +206,7 @@ end add_section!(wing, [0.0, y, 0.0], [-1.0, y, 0.0], INVISCID) end - refine_aerodynamic_mesh!(wing) + refine!(wing) sections = wing.refined_sections @test length(sections) == wing.n_panels + 1 @@ -226,7 +226,7 @@ end add_section!(wing, [0.0, 5.0, 0.0], [-1.0, 5.0, 0.0], INVISCID) add_section!(wing, [0.0, -5.0, 0.0], [-1.0, -5.0, 0.0], INVISCID) - refine_aerodynamic_mesh!(wing) + refine!(wing) sections = wing.refined_sections # Calculate expected quarter-chord points @@ -284,7 +284,7 @@ end add_section!(wing, [0.0, 0.0, 0.0], [-1.0, 0.0, 0.0], LEI_AIRFOIL_BREUKELS, (2.0, 0.5)) add_section!(wing, [0.0, -span/2, 0.0], [-1.0, -span/2, 0.0], LEI_AIRFOIL_BREUKELS, (4.0, 1.0)) - refine_aerodynamic_mesh!(wing) + refine!(wing) sections = wing.refined_sections @test length(sections) == wing.n_panels + 1 @@ -316,7 +316,7 @@ end add_section!(wing, [0.0, -1.0, 0.0], [1.0, -1.0, 0.0], INVISCID) add_section!(wing, [0.0, -2.0, 0.0], [1.0, -2.0, 0.0], INVISCID) - refine_aerodynamic_mesh!(wing) + refine!(wing) new_sections = wing.refined_sections @test length(new_sections) - 1 == 6 @@ -346,7 +346,7 @@ end add_section!(wing, [0.0, 0.0, 0.0], [1.0, 0.0, 0.0], INVISCID) add_section!(wing, [0.0, -span/2, 0.0], [1.0, -span/2, 0.0], INVISCID) - refine_aerodynamic_mesh!(wing) + refine!(wing) @test length(wing.refined_panel_mapping) == n_panels @@ -391,7 +391,7 @@ end add_section!(wing, [0.0, -span/6, 0.0], [1.0, -span/6, 0.0], INVISCID) add_section!(wing, [0.0, -span/2, 0.0], [1.0, -span/2, 0.0], INVISCID) - refine_aerodynamic_mesh!(wing) + refine!(wing) @test length(wing.refined_panel_mapping) == n_panels @@ -435,7 +435,7 @@ end add_section!(wing, [0.0, -2.0, 0.0], [1.0, -2.0, 0.0], INVISCID) add_section!(wing, [0.0, -6.0, 0.0], [1.0, -6.0, 0.0], INVISCID) - refine_aerodynamic_mesh!(wing) + refine!(wing) @test length(wing.refined_panel_mapping) == n_panels diff --git a/test/yaml_geometry/test_wing_constructor.jl b/test/yaml_geometry/test_wing_constructor.jl index e0acf4a9..bdd19f5d 100644 --- a/test/yaml_geometry/test_wing_constructor.jl +++ b/test/yaml_geometry/test_wing_constructor.jl @@ -41,7 +41,6 @@ using Logging @test wing isa Wing @test wing.n_panels == 4 - @test wing.n_unrefined_sections == 2 @test wing.spanwise_distribution == LINEAR @test wing.spanwise_direction ≈ [0.0, 1.0, 0.0] @test length(wing.unrefined_sections) == 2 # simple_wing has 2 sections @@ -77,7 +76,6 @@ using Logging ) @test wing.n_panels == 8 - @test wing.n_unrefined_sections == 2 @test wing.spanwise_distribution == COSINE @test !wing.remove_nan end @@ -188,7 +186,6 @@ wing_airfoils: wing = Wing(test_yaml_path; n_panels=12) @test wing.n_panels == 12 - @test wing.n_unrefined_sections == 7 @test length(wing.unrefined_sections) == 7 # Test that different airfoil_ids get different polar data @@ -219,7 +216,6 @@ wing_airfoils: @test wing isa Wing @test wing.n_panels == 6 - @test wing.n_unrefined_sections == 2 @test wing.spanwise_distribution == COSINE @test length(wing.unrefined_sections) == 2 @test wing.unrefined_sections[1].aero_model == POLAR_VECTORS @@ -235,17 +231,15 @@ wing_airfoils: wing = Wing(simple_wing_file; n_panels=4) @test wing isa Wing @test wing.n_panels == 4 - @test wing.n_unrefined_sections == 2 @test length(wing.unrefined_sections) == 2 - + # Test complex wing construction complex_wing_file = test_data_path("yaml_geometry", "complex_wing.yaml") @test isfile(complex_wing_file) - + complex_wing = Wing(complex_wing_file; n_panels=12) @test complex_wing isa Wing @test complex_wing.n_panels == 12 - @test complex_wing.n_unrefined_sections == 7 @test length(complex_wing.unrefined_sections) == 7 # Verify polar data is loaded from shared files diff --git a/test/yaml_geometry/test_yaml_wing_deformation.jl b/test/yaml_geometry/test_yaml_wing_deformation.jl index bf263cc5..6194e676 100644 --- a/test/yaml_geometry/test_yaml_wing_deformation.jl +++ b/test/yaml_geometry/test_yaml_wing_deformation.jl @@ -7,6 +7,7 @@ using Test # Load existing simple_wing.yaml simple_wing_file = test_data_path("yaml_geometry", "simple_wing.yaml") wing = Wing(simple_wing_file; n_panels=4) + refine!(wing) body_aero = BodyAerodynamics([wing]) # Store original TE point for comparison @@ -19,7 +20,7 @@ using Test delta_dist = fill(deg2rad(5.0), wing.n_panels) # 5 degrees TE deflection per panel VortexStepMethod.deform!(wing, theta_dist, delta_dist) - VortexStepMethod.reinit!(body_aero; refine_mesh=false) + VortexStepMethod.reinit!(body_aero) # Check if TE point changed after deformation deformed_te_point = copy(body_aero.panels[i].TE_point_1) @@ -40,7 +41,7 @@ using Test zero_delta_dist = zeros(wing.n_panels) VortexStepMethod.deform!(wing, zero_theta_dist, zero_delta_dist) - VortexStepMethod.reinit!(body_aero; refine_mesh=false) + VortexStepMethod.reinit!(body_aero) # Check if TE point returned to original position reset_te_point = copy(body_aero.panels[i].TE_point_1) @@ -54,6 +55,7 @@ using Test # Load existing complex_wing.yaml with multiple sections complex_wing_file = test_data_path("yaml_geometry", "complex_wing.yaml") wing = Wing(complex_wing_file; n_panels=12) + refine!(wing) body_aero = BodyAerodynamics([wing]) # Store original points for multiple panels @@ -72,7 +74,7 @@ using Test delta_dist = [deg2rad(-5.0 + 10.0 * i / n) for i in 1:n] # Varying deflection VortexStepMethod.deform!(wing, theta_dist, delta_dist) - VortexStepMethod.reinit!(body_aero; refine_mesh=false) + VortexStepMethod.reinit!(body_aero) # Check that different panels have different deformations for (idx, i) in enumerate(test_indices) @@ -91,7 +93,7 @@ using Test # Reset and verify VortexStepMethod.deform!(wing, zeros(wing.n_panels), zeros(wing.n_panels)) - VortexStepMethod.reinit!(body_aero; refine_mesh=false) + VortexStepMethod.reinit!(body_aero) for (idx, i) in enumerate(test_indices) reset_te = body_aero.panels[i].TE_point_1 @@ -106,6 +108,7 @@ using Test # This test specifically checks the NTuple handling fix simple_wing_file = test_data_path("yaml_geometry", "simple_wing.yaml") wing = Wing(simple_wing_file; n_panels=4) + refine!(wing) # Verify that sections have NTuple aero_data (for wings with simple polars) # or other valid AeroData types @@ -127,13 +130,14 @@ using Test # Test that reinit! on BodyAerodynamics properly handles deformed wings simple_wing_file = test_data_path("yaml_geometry", "simple_wing.yaml") wing = Wing(simple_wing_file; n_panels=4) + refine!(wing) body_aero = BodyAerodynamics([wing]) # Apply deformation theta_dist = fill(deg2rad(15.0), wing.n_panels) delta_dist = fill(deg2rad(3.0), wing.n_panels) VortexStepMethod.deform!(wing, theta_dist, delta_dist) - VortexStepMethod.reinit!(body_aero; refine_mesh=false) + VortexStepMethod.reinit!(body_aero) # Store state after deformation i = length(body_aero.panels) ÷ 2 @@ -144,7 +148,7 @@ using Test va=zeros(3), omega=zeros(3), init_aero=true, - refine_mesh=false + ) end @@ -155,11 +159,12 @@ using Test @testset "Edge Cases" begin simple_wing_file = test_data_path("yaml_geometry", "simple_wing.yaml") wing = Wing(simple_wing_file; n_panels=2) + refine!(wing) body_aero = BodyAerodynamics([wing]) # Test zero deformation VortexStepMethod.deform!(wing, zeros(wing.n_panels), zeros(wing.n_panels)) - VortexStepMethod.reinit!(body_aero; refine_mesh=false) + VortexStepMethod.reinit!(body_aero) @test all(p.delta ≈ 0.0 for p in body_aero.panels) # Test large deformation angles @@ -168,14 +173,14 @@ using Test # Should not error even with large angles VortexStepMethod.deform!(wing, theta_dist, delta_dist) - VortexStepMethod.reinit!(body_aero; refine_mesh=false) + VortexStepMethod.reinit!(body_aero) @test all(p.delta ≈ deg2rad(30.0) for p in body_aero.panels) # Test negative angles theta_dist = fill(deg2rad(-20.0), wing.n_panels) delta_dist = fill(deg2rad(-10.0), wing.n_panels) VortexStepMethod.deform!(wing, theta_dist, delta_dist) - VortexStepMethod.reinit!(body_aero; refine_mesh=false) + VortexStepMethod.reinit!(body_aero) @test all(p.delta ≈ deg2rad(-10.0) for p in body_aero.panels) end @@ -183,6 +188,7 @@ using Test # Test that panel angles are correctly averaged to section angles simple_wing_file = test_data_path("yaml_geometry", "simple_wing.yaml") wing = Wing(simple_wing_file; n_panels=4) + refine!(wing) body_aero = BodyAerodynamics([wing]) # Create varying panel angles @@ -200,7 +206,7 @@ using Test # Section 5: should use panel 4 angle = 40° # We can verify this by checking that delta values are correct - VortexStepMethod.reinit!(body_aero; refine_mesh=false) + VortexStepMethod.reinit!(body_aero) # Each panel gets its delta directly @test body_aero.panels[1].delta ≈ deg2rad(5.0) atol=1e-6 @@ -214,6 +220,7 @@ using Test # Use complex_wing which has 7 unrefined sections complex_wing_file = test_data_path("yaml_geometry", "complex_wing.yaml") wing = Wing(complex_wing_file; n_panels=12) + refine!(wing) body_aero = BodyAerodynamics([wing]) # Verify we have 7 unrefined sections @@ -226,7 +233,7 @@ using Test # Apply using unrefined_deform! VortexStepMethod.unrefined_deform!(wing, theta_unrefined, delta_unrefined) - VortexStepMethod.reinit!(body_aero; refine_mesh=false) + VortexStepMethod.reinit!(body_aero) # Each panel should have the delta from its mapped unrefined section for i in 1:wing.n_panels @@ -240,6 +247,7 @@ using Test # Create test wing with 2 unrefined sections, refined to 40 panels simple_wing_file = test_data_path("yaml_geometry", "simple_wing.yaml") wing = Wing(simple_wing_file; n_panels=40) + refine!(wing) @test wing.n_unrefined_sections == 2 # Define varying input angles at unrefined section level From d3bc096eb8fe7938c2fe87bc96eb3ca2e08d4c70 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sun, 7 Dec 2025 21:30:10 +0100 Subject: [PATCH 50/86] Move Obj to refinement method --- src/obj_geometry.jl | 114 +++++++++++++++++++++++++++++++++++-------- src/wing_geometry.jl | 6 +-- 2 files changed, 96 insertions(+), 24 deletions(-) diff --git a/src/obj_geometry.jl b/src/obj_geometry.jl index bd0a56e6..ea9863ca 100644 --- a/src/obj_geometry.jl +++ b/src/obj_geometry.jl @@ -227,6 +227,94 @@ function create_interpolations(vertices, circle_center_z, radius, gamma_tip, R=I return (le_interp, te_interp, area_interp) end +""" + refine_obj_wing!(wing::AbstractWing; recompute_mapping=true) + +Refine OBJ wing by computing position deltas and applying them to refined sections. + +This method enables deformation support for OBJ wings by: +1. Recalculating evenly-spaced gammas for unrefined sections +2. Computing what unrefined sections SHOULD be (from interpolations) +3. Computing deltas between current and interpolated positions +4. Creating refined sections from interpolations + interpolated deltas +5. Computing panel mapping + +# Arguments +- `wing::AbstractWing`: OBJ wing with le_interp/te_interp +- `recompute_mapping::Bool=true`: Whether to recompute refined_panel_mapping + +# Effects +Updates wing.refined_sections and wing.non_deformed_sections in-place. +""" +function refine_obj_wing!(wing::AbstractWing; recompute_mapping=true) + n_unrefined = wing.n_unrefined_sections + n_refined = wing.n_panels + 1 + + # 1. Calculate evenly spaced gammas for unrefined sections + unrefined_gammas = range(-wing.gamma_tip, wing.gamma_tip, n_unrefined) + + # 2. Recalculate what unrefined sections SHOULD be from interpolations + interpolated_unrefined_le = Matrix{Float64}(undef, n_unrefined, 3) + interpolated_unrefined_te = Matrix{Float64}(undef, n_unrefined, 3) + for (i, gamma) in enumerate(unrefined_gammas) + interpolated_unrefined_le[i, :] .= [wing.le_interp[j](gamma) for j in 1:3] + interpolated_unrefined_te[i, :] .= [wing.te_interp[j](gamma) for j in 1:3] + end + + # 3. Compute deltas: current - interpolated + deltas_le = Matrix{Float64}(undef, n_unrefined, 3) + deltas_te = Matrix{Float64}(undef, n_unrefined, 3) + for i in 1:n_unrefined + deltas_le[i, :] .= wing.unrefined_sections[i].LE_point - + interpolated_unrefined_le[i, :] + deltas_te[i, :] .= wing.unrefined_sections[i].TE_point - + interpolated_unrefined_te[i, :] + end + + # 4. Create refined sections with interpolated deltas + refined_gammas = range(-wing.gamma_tip, wing.gamma_tip, n_refined) + if isempty(wing.refined_sections) + wing.refined_sections = [Section() for _ in 1:n_refined] + end + + for (idx, gamma) in enumerate(refined_gammas) + # Get base position from interpolation + base_le = [wing.le_interp[i](gamma) for i in 1:3] + base_te = [wing.te_interp[i](gamma) for i in 1:3] + + # Find surrounding unrefined sections for delta interpolation + unrefined_idx = searchsortedlast(collect(unrefined_gammas), gamma) + unrefined_idx = clamp(unrefined_idx, 1, n_unrefined - 1) + + # Linear interpolation weight + gamma_left = unrefined_gammas[unrefined_idx] + gamma_right = unrefined_gammas[unrefined_idx + 1] + t = (gamma - gamma_left) / (gamma_right - gamma_left) + + # Interpolate deltas + delta_le = (1 - t) * deltas_le[unrefined_idx, :] + + t * deltas_le[unrefined_idx + 1, :] + delta_te = (1 - t) * deltas_te[unrefined_idx, :] + + t * deltas_te[unrefined_idx + 1, :] + + # Apply deltas to get final position + final_le = base_le + delta_le + final_te = base_te + delta_te + + # Update refined section + aero_model = wing.unrefined_sections[1].aero_model + aero_data = wing.unrefined_sections[1].aero_data + VortexStepMethod.reinit!(wing.refined_sections[idx], final_le, final_te, + aero_model, aero_data) + end + + # 5. Compute panel mapping and update non_deformed_sections + recompute_mapping && VortexStepMethod.compute_refined_panel_mapping!(wing) + VortexStepMethod.update_non_deformed_sections!(wing) + + return nothing +end + """ center_to_com!(vertices, faces) @@ -487,34 +575,18 @@ function ObjWing( push!(sections, Section(LE_point, TE_point, POLAR_MATRICES, aero_data)) end - # Create refined sections (evenly spaced including both tips) - refined_sections = Section[] - for gamma in range(-gamma_tip, gamma_tip, n_panels+1) - LE_point = [le_interp[i](gamma) for i in 1:3] - TE_point = [te_interp[i](gamma) for i in 1:3] - push!(refined_sections, Section(LE_point, TE_point, POLAR_MATRICES, aero_data)) - end - - # Create non_deformed_sections as copy of refined_sections for deformation support - non_deformed_sections = [Section() for _ in 1:n_panels+1] - for i in 1:n_panels+1 - reinit!(non_deformed_sections[i], refined_sections[i]) - end - panel_props = PanelProperties{n_panels}() cache = [PreallocationTools.LazyBufferCache()] wing = Wing(n_panels, Int16(n_unrefined_sections), spanwise_distribution, panel_props, MVec3(spanwise_direction), - sections, refined_sections, remove_nan, - Int16[], - non_deformed_sections, zeros(n_panels), zeros(n_panels), + sections, Section[], remove_nan, # refined_sections empty + Int16[], # refined_panel_mapping empty + Section[], zeros(n_panels), zeros(n_panels), # non_deformed, theta, delta mass, gamma_tip, inertia_tensor, T_cad_body, R_cad_body, radius, le_interp, te_interp, area_interp, cache) - # Compute panel mapping for deformation support - VortexStepMethod.compute_refined_panel_mapping!(wing) - - # Update panel properties + # Auto-refine for backward compatibility + refine_obj_wing!(wing; recompute_mapping=true) reinit!(wing) wing diff --git a/src/wing_geometry.jl b/src/wing_geometry.jl index 5f2acfa4..241b2bc3 100644 --- a/src/wing_geometry.jl +++ b/src/wing_geometry.jl @@ -580,7 +580,7 @@ Add a new section to the wing. - `aero_model`::AeroModel: [AeroModel](@ref) - `aero_data`::AeroData: See [AeroData](@ref) """ -function add_section!(wing::Wing, LE_point, +function add_section!(wing::Wing, LE_point, TE_point, aero_model::AeroModel, aero_data::AeroData=nothing) if aero_model == POLAR_VECTORS && wing.remove_nan aero_data = remove_vector_nans(aero_data) @@ -588,6 +588,7 @@ function add_section!(wing::Wing, LE_point, interpolate_matrix_nans!.(aero_data[3:5]) end push!(wing.unrefined_sections, Section(LE_point, TE_point, aero_model, aero_data)) + wing.n_unrefined_sections = Int16(length(wing.unrefined_sections)) return nothing end @@ -623,7 +624,6 @@ function update_non_deformed_sections!(wing::AbstractWing) # Populate or update non_deformed_sections if isempty(wing.non_deformed_sections) - @show length(wing.refined_sections) n_sections # Initial setup wing.non_deformed_sections = [Section() for _ in 1:n_sections] for i in 1:n_sections @@ -705,10 +705,10 @@ function refine!(wing::AbstractWing; recompute_mapping=true, sort_sections=true) n_sections = wing.n_panels + 1 if length(wing.refined_sections) == 0 - @show wing.spanwise_distribution if wing.spanwise_distribution == UNCHANGED || length(wing.unrefined_sections) == n_sections wing.refined_sections = wing.unrefined_sections + recompute_mapping && compute_refined_panel_mapping!(wing) update_non_deformed_sections!(wing) return nothing else From 662c3ebdeceefef025b308d5b10897d8011055b1 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sun, 7 Dec 2025 21:31:22 +0100 Subject: [PATCH 51/86] Add obj wing refinement test --- test/test_refinement_validation.jl | 86 ++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 test/test_refinement_validation.jl diff --git a/test/test_refinement_validation.jl b/test/test_refinement_validation.jl new file mode 100644 index 00000000..0555b707 --- /dev/null +++ b/test/test_refinement_validation.jl @@ -0,0 +1,86 @@ +using VortexStepMethod +using Test + +@testset "Refinement Validation" begin + @testset "Error when refinement forgotten" begin + wing = Wing(20; spanwise_distribution=LINEAR) + add_section!(wing, [0,10,0], [1,10,0], INVISCID) + add_section!(wing, [0,-10,0], [1,-10,0], INVISCID) + + # Should error without refinement + @test_throws ArgumentError BodyAerodynamics([wing]) + + # Should work after refinement + refine!(wing) + body_aero = BodyAerodynamics([wing]) + @test length(body_aero.panels) == 20 + end + + @testset "Multiple refine! calls work correctly" begin + wing = Wing(20; spanwise_distribution=LINEAR) + add_section!(wing, [0,10,0], [1,10,0], INVISCID) + add_section!(wing, [0,-10,0], [1,-10,0], INVISCID) + + # Multiple calls should work (not idempotent - re-refines each time) + refine!(wing) + n1 = length(wing.refined_sections) + + refine!(wing) + n2 = length(wing.refined_sections) + + @test n1 == n2 == 21 + end + + @testset "YAML wing deformation support after refinement" begin + simple_wing_file = test_data_path("yaml_geometry", "simple_wing.yaml") + wing = Wing(simple_wing_file; n_panels=4) + + # After refinement, should have non_deformed_sections + refine!(wing) + @test !isempty(wing.non_deformed_sections) + @test length(wing.non_deformed_sections) == 5 + + # unrefined_deform! should work + @test_nowarn VortexStepMethod.unrefined_deform!(wing, [0.1, 0.2], nothing) + end + + @testset "ObjWing deformation support" begin + data_dir = joinpath(dirname(@__DIR__), "data", "ram_air_kite") + wing = ObjWing( + joinpath(data_dir, "ram_air_kite_body.obj"), + joinpath(data_dir, "ram_air_kite_foil.dat"); + n_panels=20, + n_unrefined_sections=2, + prn=false + ) + + # ObjWing creates non_deformed_sections in constructor (no refine! needed) + @test !isempty(wing.non_deformed_sections) + @test length(wing.non_deformed_sections) == 21 + + # unrefined_deform! should work + @test_nowarn VortexStepMethod.unrefined_deform!(wing, deg2rad.([5.0, -5.0]), nothing) + end + + @testset "Refinement populates all required fields" begin + wing = Wing(10; spanwise_distribution=COSINE) + add_section!(wing, [0,5,0], [1,5,0], INVISCID) + add_section!(wing, [0,-5,0], [1,-5,0], INVISCID) + + refine!(wing) + + # Check refined_sections populated + @test length(wing.refined_sections) == 11 + + # Check non_deformed_sections populated + @test length(wing.non_deformed_sections) == 11 + + # Check theta_dist and delta_dist resized + @test length(wing.theta_dist) == 10 + @test length(wing.delta_dist) == 10 + + # Check all zeros initially + @test all(wing.theta_dist .== 0.0) + @test all(wing.delta_dist .== 0.0) + end +end From 56687a4d7beddf14057c17e15ce51916e3b6aec7 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sun, 7 Dec 2025 21:55:08 +0100 Subject: [PATCH 52/86] Auto refine yaml wing --- src/yaml_geometry.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/yaml_geometry.jl b/src/yaml_geometry.jl index 4df42382..e6c39514 100644 --- a/src/yaml_geometry.jl +++ b/src/yaml_geometry.jl @@ -262,6 +262,7 @@ function Wing( add_section!(wing, le_coord, te_coord, aero_model, aero_data) end + refine!(wing) return wing end From 25fb6f0bb4979da801a1b3c5b7b4709f442cec61 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Wed, 10 Dec 2025 21:25:26 +0100 Subject: [PATCH 53/86] Width is sum not average --- src/solver.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/solver.jl b/src/solver.jl index 3ec3c376..88e997a2 100644 --- a/src/solver.jl +++ b/src/solver.jl @@ -386,7 +386,6 @@ function solve!(solver::Solver, body_aero::BodyAerodynamics, gamma_distribution= z_airf_unrefined_dist[target_unrefined_idx] ./= count va_unrefined_dist[target_unrefined_idx] ./= count chord_unrefined_dist[target_unrefined_idx] /= count - width_unrefined_dist[target_unrefined_idx] /= count end end unrefined_idx += wing.n_unrefined_sections From 01a418cf5ed719087f4e4e3a930013e029be9ae6 Mon Sep 17 00:00:00 2001 From: jellepoland Date: Fri, 2 Jan 2026 14:21:43 +0100 Subject: [PATCH 54/86] adjusted V3_kite example, added literature plotting to MakieExt, changed alpha_geometric to angle between va and chord, changed settings_jl to default the corrected_aoa to false --- data/TUDELFT_V3_KITE/aero_geometry.yaml | 2 +- ..._Rey_5e5_Poland2025_alpha_sweep_beta_0.csv | 81 +++--- ...y_5e5_n36_CFD_PCHIP_polars_alpha_sweep.csv | 63 ----- data/TUDELFT_V3_KITE/vsm_settings.yaml | 1 + examples/V3_kite.jl | 7 +- ext/VortexStepMethodMakieExt.jl | 230 +++++++++++++----- src/body_aerodynamics.jl | 24 +- src/settings.jl | 8 +- 8 files changed, 243 insertions(+), 173 deletions(-) delete mode 100644 data/TUDELFT_V3_KITE/literature_results/Python_VSM_Rey_5e5_n36_CFD_PCHIP_polars_alpha_sweep.csv diff --git a/data/TUDELFT_V3_KITE/aero_geometry.yaml b/data/TUDELFT_V3_KITE/aero_geometry.yaml index d830911a..1c73c172 100644 --- a/data/TUDELFT_V3_KITE/aero_geometry.yaml +++ b/data/TUDELFT_V3_KITE/aero_geometry.yaml @@ -79,7 +79,7 @@ wing_airfoils: # - inviscid: # no further data is required # --------------------------------------------------------------- - alpha_range: [-10, 31, 0.5] # [deg], in this range the polars are calculated + alpha_range: [-10, 25, 0.5] # [deg], in this range the polars are calculated reynolds: !!float 1e6 # Reynolds number headers: [airfoil_id, type, info_dict] data: diff --git a/data/TUDELFT_V3_KITE/literature_results/Python_VSM_Rey_5e5_Poland2025_alpha_sweep_beta_0.csv b/data/TUDELFT_V3_KITE/literature_results/Python_VSM_Rey_5e5_Poland2025_alpha_sweep_beta_0.csv index 65726bed..5d2b4246 100644 --- a/data/TUDELFT_V3_KITE/literature_results/Python_VSM_Rey_5e5_Poland2025_alpha_sweep_beta_0.csv +++ b/data/TUDELFT_V3_KITE/literature_results/Python_VSM_Rey_5e5_Poland2025_alpha_sweep_beta_0.csv @@ -1,39 +1,42 @@ -alpha,CL,CD,CL/CD,CS --12.0,-0.2382871512913027,0.10555351086138359,-2.2575009523295666,8.493387378390686e-14 --11.0,-0.23078413996904473,0.10186112684362705,-2.265674326608765,6.616874649497016e-14 --10.0,-0.22230140038021914,0.09806363640487119,-2.266909616347621,4.373272668096159e-14 --9.0,-0.21585315982172304,0.0931590398953698,-2.317039334713575,2.739682786368477e-14 --8.0,-0.20625706590216833,0.08814998331707347,-2.339842370250558,1.1046588689401156e-14 --7.0,-0.1998343140258721,0.08290261953105998,-2.410470442987666,-2.389661935808156e-14 --6.0,-0.18199775713691974,0.07765158375393942,-2.343773923705537,-3.872611350474041e-14 --5.0,-0.14850648581010087,0.07109437185188841,-2.0888641666246923,-3.2393754503524565e-14 --4.0,-0.10858858872468641,0.06522454108866148,-1.6648425103839215,-3.0271060429342046e-14 --3.0,-0.06288342322853809,0.06000714503007155,-1.0479322620168838,-2.895668145826433e-14 --2.0,-0.007429949914950523,0.055498453779690086,-0.13387670122207165,-3.2169539191587655e-14 --1.0,0.05656004203302359,0.05159811771021331,1.0961648320327801,-3.44716398526909e-14 -0.0,0.12392449645064037,0.04839062569141725,2.5609194896733913,-3.597944298611074e-14 -1.0,0.19309362003485317,0.04593968204080192,4.203198878550238,-3.699581064093612e-14 -2.0,0.2625331911314792,0.044328371503610776,5.922464151657241,-3.6349856219703554e-14 -3.0,0.3323792213186091,0.04356996032047687,7.628632637574346,-3.6413469417385087e-14 -4.0,0.40297413442239444,0.04359394940688724,9.243808829092464,-3.773253515649088e-14 -5.0,0.4734826904404322,0.04438413803893367,10.667835658430365,-3.826806223929053e-14 -6.0,0.5430144326845379,0.04590240400649957,11.829760214903983,-4.0253505670851383e-14 -7.0,0.610689137470121,0.04806877475261435,12.704487281255428,-4.406262078692334e-14 -8.0,0.6758859112182876,0.05085291168580261,13.290997286336015,-4.723118897422392e-14 -9.0,0.7383699770457292,0.054242295408895566,13.612439729544315,-5.20455622927876e-14 -10.0,0.7982179068869607,0.05807229829781809,13.74524395079696,-5.5385868816441935e-14 -11.0,0.8557802537306283,0.062209616690946774,13.756398114170796,-5.702371714996311e-14 -12.0,0.8988323082495834,0.0690977304744752,13.008130687904623,-6.141415623852904e-14 -13.0,0.9147135983203839,0.08124056010481986,11.259321663220728,6.491282774779828e-13 -14.0,0.9112748609115651,0.0966853408597458,9.425160554933385,4.54748749597064e-13 -15.0,0.9085348699441353,0.11140779158846578,8.155038862095148,3.3836985824286487e-13 -16.0,0.9062580847970818,0.1257712798490804,7.2056043787146695,2.6754981159878576e-13 -17.0,0.8882638215990443,0.13985252773614038,6.3514320118327126,4.0927876403191203e-13 -18.0,0.8801641114980264,0.15426592918480644,5.7054990440800015,2.5988028226070375e-13 -19.0,0.8799535802082414,0.16798064710830107,5.238422373982847,1.821903726884496e-13 -20.0,0.8812698509369349,0.18370556270697425,4.797186530179459,1.3007693874618696e-13 -21.0,0.871379428960392,0.198621428734149,4.387137050185641,5.975307998613411e-15 -22.0,0.8680573492907033,0.21572711063981947,4.023867685040394,-1.822880946847326e-15 -23.0,0.8639910136639356,0.23075669712075686,3.7441644140529626,-5.408316146275571e-16 -24.0,0.8613474653095494,0.24594284553183446,3.5022261511488364,-4.729369019706576e-15 -25.0,0.8583553232582976,0.2571571564052344,3.3378628666498424,-7.613518753563846e-15 +aoa,CL,CD,CL/CD,CS,CMx,CMy,CMz +-10.0,-0.2899438548536225,0.11444148940320673,-2.5335554121641666,1.2632849420097243e-16,-4.647882087149715e-16,0.241005708121509,1.3320808460460066e-17 +-9.0,-0.259323389193173,0.10427582213610573,-2.486898533916058,8.133720087520711e-17,-3.0727864921628827e-16,0.2441118737914144,2.5201529519789312e-17 +-8.0,-0.22875311476552543,0.09366499220052174,-2.442247731957332,1.0650880027838038e-16,-3.805430957488186e-16,0.24059440159863246,2.7271655158914863e-17 +-7.0,-0.20635291039990597,0.0860095396962368,-2.399186312689156,1.488241408638551e-16,-3.9881420465066586e-16,0.23899635317310408,4.995303172672525e-18 +-6.0,-0.1866842911582697,0.0799403806962401,-2.3352939970055733,1.6379183256504107e-16,-4.333763022778055e-16,0.2387816842533537,3.600218502827045e-19 +-5.0,-0.15629307905527645,0.07310015148280119,-2.1380677862486874,1.1333100946241802e-16,-3.313101077226588e-16,0.2370962750181975,2.5651556832642695e-18 +-4.0,-0.12301844746722777,0.06662724293376737,-1.8463685731303277,9.281292128068421e-17,-2.874999488163823e-16,0.2333065448951321,1.96211908404074e-17 +-3.0,-0.09480706631983721,0.061811891193387994,-1.5337997995113715,7.129043188152672e-17,-2.272891070273052e-16,0.2302740046001065,8.865538063211598e-18 +-2.0,-0.07916131296641464,0.05824350777665392,-1.359143979960378,5.678312902748551e-17,-1.8124850025169902e-16,0.22607192662608816,7.20043700565409e-19 +-1.0,-0.0006740478672329941,0.052944155178660766,-0.012731298949967385,3.769858695662166e-17,-1.3167799174089916e-16,0.21686265682236505,4.455270397248468e-18 +0.0,0.08093466522331724,0.04918101568895793,1.6456485107014294,5.493054636113047e-17,-1.5012911156788777e-16,0.20369043744652132,3.6002185028270446e-18 +1.0,0.16194506049752752,0.04720073397581787,3.430986064337391,-8.363087465259907e-17,2.3581431193517144e-16,0.18746036234454405,-1.0148115904843732e-17 +2.0,0.24303401825304724,0.04688181680867234,5.183971842321821,-3.481679169784715e-17,5.220316829099215e-17,0.1675122904447942,-1.0710650045910458e-17 +3.0,0.32424069303788133,0.04813298779160052,6.73635084615427,-1.4550125449404366e-16,4.471471380511189e-16,0.14362060131567356,-1.4715893130305544e-17 +4.0,0.40376967010374315,0.050835078503145406,7.942737219905346,5.4342424879747936e-17,-1.404085216102548e-16,0.11620472270539715,-4.3877663003204624e-18 +5.0,0.48053613587946714,0.05473624746432928,8.779120932479428,-3.500499057188957e-16,7.510055796897215e-16,0.08490146680229291,-4.0389951328590907e-17 +6.0,0.5545682579333404,0.0596712070015607,9.293732870508816,-5.763590517549021e-17,1.1016668618650757e-16,0.04893466753539431,-2.2411360180098355e-17 +7.0,0.6260573361570156,0.06554944992629715,9.550916702748008,-3.269955436486996e-16,9.410971166389895e-16,0.007745970661612456,-4.66790830257169e-17 +8.0,0.6950297274681769,0.07232159791097642,9.610265087390866,-3.0911665061466996e-16,9.259761989271158e-16,-0.038577142430600606,-6.829164472550051e-17 +9.0,0.7615412964040593,0.07997443153978162,9.522309589974972,-3.147626168359425e-16,7.920480706219498e-16,-0.08953081338203528,-5.654593186002727e-17 +10.0,0.8249202325681747,0.08844390592694658,9.327044344350274,-1.689084894530693e-16,6.278781068930366e-16,-0.14441723630425013,-4.9908028995439906e-17 +11.0,0.8857305295440444,0.09773754259249884,9.062336805795876,-3.834552058614247e-16,1.4775296735602192e-15,-0.2029784466166877,-1.169620986105936e-16 +12.0,0.8860193862870925,0.11733281778052011,7.551334767604906,-4.4367884555499816e-16,8.410110422603976e-16,-0.19610604138765558,-1.2740273226879205e-16 +13.0,0.9423029692906789,0.12831017804038788,7.343945614307171,-9.739291731695082e-16,2.4783904173461378e-15,-0.25789488481163775,-2.3945953316928383e-16 +14.0,0.9053263590334583,0.15430047546121956,5.8672946815448705,-6.389351773740059e-16,1.4602486247466493e-15,-0.20122170636859626,-1.9706696029849537e-16 +15.0,0.9694562131148579,0.16857887458133222,5.750757415616367,-4.493248117762704e-16,1.2917583988143429e-15,-0.2674244424602687,-1.4832900231647417e-16 +16.0,0.9758322646713564,0.18570904148435918,5.2546298062366725,-5.980019222697798e-16,1.6215384136733e-15,-0.27786494227196934,-8.793533693155052e-17 +17.0,0.9448836636848859,0.20633957470152428,4.579265344768134,-3.1993808587210893e-17,4.4354691954829193e-16,-0.24538493714556528,-2.8891753485187034e-17 +18.0,0.961850379043191,0.16843106939328223,5.710646987565549,-3.834552058614248e-16,1.0599043272322824e-15,-0.46225819118880307,-2.4301474894082562e-17 +19.0,0.9267597351824522,0.1850581617382613,5.007937647695989,1.9102185715305329e-16,-7.200437005654089e-18,-0.4335709883970577,-5.0403059039578624e-17 +20.0,0.9179029310454382,0.2035493416172546,4.5094861214114035,-2.3524859255302127e-18,5.342724258195335e-16,-0.42360899506222816,2.41214639689412e-17 +21.0,0.8965458184017534,0.22152181272395435,4.047212359710007,-8.29016040156847e-16,2.2321354717527677e-15,-0.40379164605102685,-1.2600764759894656e-16 +22.0,0.8906571907163747,0.23809291397562277,3.740796716056678,-3.787502340103643e-16,1.4904904601703965e-15,-0.4027984881057474,-1.3914844513426527e-16 +23.0,0.8699997908511103,0.25414602903330513,3.4232279534735492,-4.013340988954543e-16,1.3623226814697537e-15,-0.3851865349999547,-8.478514574157691e-17 +24.0,0.8676877420424984,0.25647010500429335,3.3831925246335173,-2.352485925530213e-16,9.144554997180693e-16,-0.4337238093839038,-1.9675194117949799e-16 +25.0,,,,,,, +26.0,,,,,,, +27.0,,,,,,, +28.0,,,,,,, +29.0,,,,,,, +30.0,,,,,,, diff --git a/data/TUDELFT_V3_KITE/literature_results/Python_VSM_Rey_5e5_n36_CFD_PCHIP_polars_alpha_sweep.csv b/data/TUDELFT_V3_KITE/literature_results/Python_VSM_Rey_5e5_n36_CFD_PCHIP_polars_alpha_sweep.csv deleted file mode 100644 index b6f0c626..00000000 --- a/data/TUDELFT_V3_KITE/literature_results/Python_VSM_Rey_5e5_n36_CFD_PCHIP_polars_alpha_sweep.csv +++ /dev/null @@ -1,63 +0,0 @@ -alpha,CL,CD,CS,CMx,CMy,CMz --5.0,-0.016639150841432696,0.06461257742824286,8.478187720501367e-17,-3.061887882386819e-16,0.28227103088648064,3.1640606750175953e-17 --4.508196721311475,-0.15116141710337438,0.06813042331168648,1.6558287946512188e-16,-4.3472875316127167e-16,0.2448193040108129,2.741773931281523e-17 --4.016393442622951,-0.12359435503424275,0.06467079023399522,2.22928996914706e-16,-5.896358903756748e-16,0.24394876629214812,1.3945762219966873e-17 --3.5245901639344264,-0.0955075625757297,0.06140805998980694,2.3960563519741807e-16,-6.054561937507627e-16,0.2420546192298006,1.9095600558211657e-17 --3.0327868852459017,-0.08614032786011963,0.059727576261926124,2.560670910506758e-16,-6.24901983315975e-16,0.24100968398007022,2.597578457810669e-17 --2.540983606557377,-0.0552050539665637,0.05704706679467209,3.208907979237986e-16,-8.223261858509271e-16,0.23846691212426813,3.934476490419015e-17 --2.0491803278688527,-0.023671564731756238,0.054662724982745055,2.9679036582491142e-16,-7.499812568752643e-16,0.23501881516673262,2.978666494840783e-17 --1.557377049180328,0.008844196939017434,0.05251409193106237,3.002063868924993e-16,-7.601161387249302e-16,0.23045212739790363,2.5090012383928592e-17 --1.0655737704918034,0.0415747891970653,0.05060381840435065,2.890169005608731e-16,-7.430804735020164e-16,0.22471056723584462,1.614989302873564e-17 --0.5737704918032787,0.07502466254074833,0.04891798700234494,3.0738810047553817e-16,-7.754008589128406e-16,0.2177951282212764,2.830351150699333e-17 --0.08196721311475397,0.10889694335333432,0.047464944609758454,2.84202193701832e-16,-7.096065243034252e-16,0.20978226669304198,2.2494493861453216e-17 -0.4098360655737707,0.14309203022027436,0.04622054569950249,2.4401687500123214e-16,-5.785946369784777e-16,0.20048986627783982,1.1103051457255748e-17 -0.9016393442622945,0.1780413579153343,0.04526384343079455,2.669338037381205e-16,-7.267451862931039e-16,0.19045131694925846,2.0985591228347496e-17 -1.3934426229508192,0.21395263479636484,0.04447997622080856,2.912494182664618e-16,-8.450678719526157e-16,0.17884135671129764,1.8766010904563983e-17 -1.885245901639344,0.250813572958965,0.04389188664361113,1.9097440614073512e-16,-4.643918219895616e-16,0.16568961707932453,1.408995769343773e-17 -2.3770491803278686,0.28895949644132035,0.04350125508066167,4.0626442680981155e-16,-1.014476953927516e-15,0.1508258269234812,4.0539527398662916e-17 -2.8688524590163933,0.3273497069332273,0.04329404509617653,1.2824872795479226e-16,-3.203611433455315e-16,0.1341391252119524,3.275297183123682e-17 -3.360655737704917,0.365700349792079,0.04337836667220271,1.9990447696309065e-16,-4.080319912158108e-16,0.11648263639587733,1.936339215180039e-17 -3.8524590163934427,0.40370330464829807,0.04368762204422157,2.816738001557434e-16,-7.916743480616941e-16,0.09735955183971143,1.9610584392036138e-17 -4.3442622950819665,0.4404116927505139,0.044306322502976996,1.6375382881475996e-16,-3.8232399823129283e-16,0.07791841285021213,2.315367316874855e-17 -4.836065573770492,0.4762504901989163,0.04515131620054717,2.369158548292387e-16,-6.24901983315975e-16,0.057514814009507295,2.0764148179802968e-17 -5.327868852459016,0.5109687991364886,0.04622052439565633,9.209807980646155e-17,-4.073728119085154e-16,0.03637335615544438,2.19177119675698e-17 -5.8196721311475414,0.5450872107517716,0.04742994878168534,2.5004198302595403e-16,-5.128415010757685e-16,0.013891257121196583,3.1640606750175953e-17 -6.311475409836065,0.578878803412755,0.04877085485214794,7.44531205912049e-17,-3.994626602209714e-16,-0.010208417088161864,9.558099955782319e-18 -6.803278688524589,0.6123151772132445,0.05025131667415033,7.316202601447877e-18,-2.412596264700915e-16,-0.03585800484077638,-1.153563787766831e-18 -7.295081967213115,0.6453702092431793,0.05185290775774244,1.441722277344141e-16,-2.9267561243912755e-16,-0.06310965707173499,2.6531967118637127e-17 -7.786885245901638,0.6779928516494528,0.053578842442153725,1.4115967372205322e-16,-4.60107156492142e-16,-0.09186632177777364,2.719114642593246e-17 -8.278688524590164,0.7101325624043433,0.055423228235985375,1.144770524697139e-16,-3.5991190178325145e-16,-0.12209448775203158,3.839719464995311e-17 -8.770491803278688,0.7417155678337713,0.057385003894413894,1.7386740299911437e-16,-5.840328662636646e-16,-0.15369844447316333,5.2075165276331265e-17 -9.262295081967213,0.7726715314550687,0.05945792991479041,-4.820086419777427e-17,1.4238273037579177e-16,-0.1866012863904165,4.7460910125263927e-17 -9.754098360655737,0.8029903119885894,0.06163976483762739,1.5364025463040542e-16,-5.589840525864415e-16,-0.2207509742279646,2.7026351599108612e-17 -10.245901639344263,0.8324426504335397,0.06391906277414598,6.842801256648311e-17,-1.8457020604269305e-17,-0.2559480287255108,6.92138272660099e-17 -10.737704918032787,0.8611093171365881,0.0662937719175855,1.4202040343987063e-17,-8.173823410462121e-17,-0.2921901366614442,5.899654800293225e-17 -11.229508196721312,0.8887836361849122,0.0687525912834733,-8.004786375701798e-17,3.4277323979357284e-17,-0.3292683490609791,3.065183778923295e-17 -11.721311475409834,0.9156238187652903,0.07131283332024405,2.1862534832561903e-16,-7.699214309209482e-16,-0.36712563062885384,7.481685137802022e-17 -12.21311475409836,0.9418984375156303,0.07399760347505731,-4.217575617305249e-17,1.6347646820924242e-16,-0.40580095808159955,4.218747566690127e-17 -12.704918032786885,0.9677215562567566,0.07682644632228418,-5.680816137594825e-17,6.328121350035191e-17,-0.4452567123584407,4.218747566690127e-17 -13.196721311475411,0.9931286743487212,0.0797870357773372,1.7386740299911434e-16,-2.794920262932209e-16,-0.48555212411561566,3.4277323979357284e-17 -13.688524590163933,0.9530080585289407,0.09372461800895182,2.0829659171181024e-16,-5.668942042739858e-16,-0.4388000351000014,2.900388952099462e-17 -14.180327868852459,0.9726783526633942,0.09816659918391062,-1.2910945767260968e-16,3.902341499188368e-16,-0.4701027130866711,5.471188250551259e-17 -14.672131147540984,0.9451834173522863,0.1086047928078909,9.667716190525011e-14,-2.2546832698452465e-13,-0.4434160867841825,2.5614389522882024e-14 -15.163934426229506,0.9274663982712807,0.1173860748560331,-1.4804551146459243e-16,1.318358614590665e-16,-0.42977676488265726,2.6696761945460965e-17 -15.655737704918032,0.9392161571013751,0.12364041059453318,3.5289918430513304e-17,-3.2431621918930353e-16,-0.4484146206820607,1.0217279263077651e-17 -16.147540983606557,0.917935061773152,0.13355092087700765,1.506277006180446e-16,-8.147456238170308e-16,-0.42684179208813605,1.100829443183205e-16 -16.639344262295083,0.9273175945900742,0.14012854861126456,-9.812318783118334e-17,1.7402333712596775e-16,-0.4427392153437181,1.4864493379509744e-16 -17.131147540983605,0.9372166929555599,0.14673903926860724,-1.2136289021225308e-15,2.6367172291813293e-15,-0.45960767742472114,-8.635248925568853e-17 -17.62295081967213,0.9212648752527602,0.15330902504856514,-7.40227557322962e-17,1.5556631652169844e-16,-0.45407537631807837,6.196285488576123e-17 -18.114754098360656,0.9042606944997617,0.1605440694312137,-5.164378306904386e-18,-2.2148424725123165e-16,-0.44298849768484955,8.701166856298387e-17 -18.606557377049178,0.9108034289591539,0.16749392814781805,1.3427383597951405e-16,-5.853512248782551e-16,-0.4553382010126988,9.492182025052785e-17 -19.098360655737704,0.8994884373576996,0.1727892443219773,7.74656746035658e-18,-2.3994126785550103e-16,-0.45765053247576365,1.1403802016209251e-16 -19.59016393442623,0.9044972557086793,0.18005479310901998,-1.7558886243474914e-16,9.492182025052785e-17,-0.4674021986963869,8.239741341191654e-17 -20.081967213114755,0.8880114648962718,0.1886092652486161,-4.2175756173052494e-17,-1.318358614590665e-16,-0.4503789890339498,1.1469719946938785e-16 -20.573770491803277,0.891661611947163,0.19581563053838055,1.7386740299911434e-16,-4.3505834281491935e-16,-0.4589643663993485,1.3315422007365713e-16 -21.065573770491802,0.8789204895652939,0.20176210132002587,2.3497921296414955e-16,-8.595698167131133e-16,-0.4538741523035905,1.9313953703753237e-16 -21.557377049180328,0.8817415797412202,0.20915497453029433,-6.283326940067003e-17,7.119136518789589e-17,-0.46087492648475836,5.5371061812807914e-17 -22.049180327868854,0.8849598383450349,0.21662460538438122,3.5289918430513304e-17,-2.610350056889516e-16,-0.46843312834521944,1.3513175799554314e-16 -22.540983606557376,0.8884516297495344,0.2240483324289815,1.807532407416535e-17,-2.610350056889516e-16,-0.47687031449324124,1.2919914422988513e-16 -23.0327868852459,0.8737106107104212,0.2339158168422375,-1.5837426807840117e-16,4.1660132221065e-16,-0.45610150036749486,7.053218588060056e-17 -23.524590163934427,0.8752551935225418,0.24200218248559524,-4.475794532650468e-17,1.2919914422988513e-16,-0.46002499798247176,2.0434558526155303e-17 -24.01639344262295,0.8768904716550766,0.24995893761794005,-8.349078262828758e-17,2.1357409556368767e-16,-0.46464194159845734,4.4824192896082596e-17 -24.508196721311474,0.8656263524743696,0.25664834099878914,-3.87328373017829e-17,4.218747566690127e-17,-0.4569579827789767,5.734859973469391e-17 -25.0,0.8663529251179094,0.2647858928603986,-1.101734038806269e-16,-5.273434458362659e-18,-0.45976462904136123,1.4567862691226844e-16 diff --git a/data/TUDELFT_V3_KITE/vsm_settings.yaml b/data/TUDELFT_V3_KITE/vsm_settings.yaml index 9f185704..d68489e3 100644 --- a/data/TUDELFT_V3_KITE/vsm_settings.yaml +++ b/data/TUDELFT_V3_KITE/vsm_settings.yaml @@ -54,6 +54,7 @@ solver_settings: # --- Core Aerodynamic Model --- aerodynamic_model_type: VSM # VSM=3D vortex method, LLT=lifting line theory solver_type: LOOP # LOOP=fixed-point iteration, NEWTON=Newton-Raphson + #correct_aoa: false # Defaults to false, meaning the computed AoA at 3/4c is used # --- Physical Properties --- density: 1.225 # [kg/m³] Air density (ISA sea level) diff --git a/examples/V3_kite.jl b/examples/V3_kite.jl index 9dafd212..45818095 100644 --- a/examples/V3_kite.jl +++ b/examples/V3_kite.jl @@ -10,7 +10,7 @@ project_dir = dirname(dirname(pathof(VortexStepMethod))) # Go up one level from literature_paths = [ joinpath(project_dir, "data", "TUDELFT_V3_KITE", "literature_results","CFD_RANS_Rey_5e5_Poland2025_alpha_sweep_beta_0_NoStruts.csv"), joinpath(project_dir, "data", "TUDELFT_V3_KITE", "literature_results","CFD_RANS_Rey_10e5_Poland2025_alpha_sweep_beta_0.csv"), - joinpath(project_dir, "data", "TUDELFT_V3_KITE", "literature_results","Python_VSM_Rey_5e5_n36_CFD_PCHIP_polars_alpha_sweep.csv"), + joinpath(project_dir, "data", "TUDELFT_V3_KITE", "literature_results","Python_VSM_Rey_5e5_Poland2025_alpha_sweep_beta_0.csv"), joinpath(project_dir, "data", "TUDELFT_V3_KITE", "literature_results","WindTunnel_Re_5e5_Poland2025_alpha_sweep_beta_0.csv"), ] labels= [ @@ -63,14 +63,15 @@ PLOT && plot_combined_analysis( results; solver_label="VSM", literature_path_list=literature_paths, - angle_range=range(-5, 25, length=30), + angle_range=range(-5, 25, length=31), angle_type="angle_of_attack", angle_of_attack=angle_of_attack_deg, side_slip=sideslip_deg, v_a=wind_speed, title="TU Delft V3 Kite", is_show=true, - use_tex=USE_TEX + use_tex=USE_TEX, + angle_of_attack_for_spanwise_distribution=10.0, ) diff --git a/ext/VortexStepMethodMakieExt.jl b/ext/VortexStepMethodMakieExt.jl index 62d5343c..02aceb03 100644 --- a/ext/VortexStepMethodMakieExt.jl +++ b/ext/VortexStepMethodMakieExt.jl @@ -698,6 +698,63 @@ function generate_polar_data_makie( return polar_data, reynolds_number[1] end +""" + compute_polar_with_cmy(solver, body_aero, angle_range; angle_type=\"angle_of_attack\", + angle_of_attack=0.0, side_slip=0.0, v_a=10.0) + +Compute CL/CD/CS polars and optional CMy for a sweep, reusing the previous gamma +as initial guess for faster convergence. Returns a named tuple with angle, +cl, cd, cs, cmy (NaN when unavailable) and per-sample Reynolds numbers. +""" +function compute_polar_with_cmy( + solver, + body_aero, + angle_range; + angle_type::String = "angle_of_attack", + angle_of_attack::Float64 = 0.0, + side_slip::Float64 = 0.0, + v_a::Float64 = 10.0 +) + n_angles = length(angle_range) + cl = zeros(n_angles) + cd = zeros(n_angles) + cs = zeros(n_angles) + cmy = fill(NaN, n_angles) # moment coefficient about body y (pitch) + reynolds_number = zeros(n_angles) + + gamma_prev = nothing + for (i, angle_i) in enumerate(angle_range) + if angle_type == "angle_of_attack" + α = deg2rad(angle_i) + β = deg2rad(side_slip) + elseif angle_type == "side_slip" + α = deg2rad(angle_of_attack) + β = deg2rad(angle_i) + else + throw(ArgumentError("angle_type must be 'angle_of_attack' or 'side_slip'")) + end + + set_va!(body_aero, [cos(α) * cos(β), sin(β), sin(α)] * v_a) + results = solve(solver, body_aero, gamma_prev) + + cl[i] = results["cl"] + cd[i] = results["cd"] + cs[i] = results["cs"] + cmy[i] = get(results, "cmy", NaN) + reynolds_number[i] = results["Rey"] + gamma_prev = results["gamma_distribution"] + end + + return ( + angle = collect(angle_range), + cl = cl, + cd = cd, + cs = cs, + cmy = cmy, + rey = reynolds_number, + ) +end + """ plot_polars(solver_list, body_aero_list, label_list; literature_path_list=String[], @@ -975,7 +1032,8 @@ function VortexStepMethod.plot_combined_analysis( literature_path_list=String[], data_type=".png", save_path=nothing, - is_save=false + is_save=false, + angle_of_attack_for_spanwise_distribution=5.0, ) # Auto-detect screen size and use 80% of it fig = try @@ -991,6 +1049,16 @@ function VortexStepMethod.plot_combined_analysis( panels = body_aero.panels va = isa(body_aero.va, Tuple) ? body_aero.va[1] : body_aero.va + # Choose results used for spanwise plots (optionally recompute at a requested AoA) + results_spanwise = results + if !isnothing(angle_of_attack_for_spanwise_distribution) + α_span = deg2rad(angle_of_attack_for_spanwise_distribution) + β_span = deg2rad(side_slip) + va_old = copy(body_aero.va) + set_va!(body_aero, [cos(α_span) * cos(β_span), sin(β_span), sin(α_span)] * v_a) + results_spanwise = solve(solver, body_aero, solver.sol.gamma_distribution) + set_va!(body_aero, va_old) + end # [1,1] Wing Geometry ax_geo = Axis3(fig[1, 1]; @@ -1039,8 +1107,8 @@ function VortexStepMethod.plot_combined_analysis( # [1,2] Polar Data Surfaces or Curves if body_aero.panels[1].aero_model == POLAR_MATRICES - alphas = collect(deg2rad.(-5:0.3:25)) - delta_tes = collect(deg2rad.(-5:0.3:25)) + alphas = collect(deg2rad.(-5:0.3:40)) + delta_tes = collect(deg2rad.(-5:0.3:40)) interp_data = [ (body_aero.panels[1].cl_interp, "Cl"), @@ -1063,19 +1131,19 @@ function VortexStepMethod.plot_combined_analysis( color=:blue, linewidth=0.5, transparency=true) end elseif body_aero.panels[1].aero_model == POLAR_VECTORS - alphas_deg = collect(-5:0.5:25) + alphas_deg = collect(-5:0.5:40) alphas = deg2rad.(alphas_deg) ax_cl_curve = Axis(fig[1, 2][1, 1]; - title="Cl vs α", + title="2D Cl vs α", xlabel="α [°]", ylabel="Cl") ax_cd_curve = Axis(fig[1, 2][1, 2]; - title="Cd vs α", + title="2DCd vs α", xlabel="α [°]", ylabel="Cd") ax_cm_curve = Axis(fig[1, 2][1, 3]; - title="Cm vs α", + title="2D Cm vs α", xlabel="α [°]", ylabel="Cm") @@ -1091,71 +1159,119 @@ function VortexStepMethod.plot_combined_analysis( # [2,1] Spanwise Distributions (3×3 grid) y_coords = [panel.aero_center[2] for panel in body_aero.panels] - ax_cl = Axis(fig[2, 1][1, 1], title="CL Distribution", - xlabel="Spanwise Position y/b", ylabel="CL") - ax_cd = Axis(fig[2, 1][1, 2], title="CD Distribution", - xlabel="Spanwise Position y/b", ylabel="CD") - ax_gamma = Axis(fig[2, 1][1, 3], title="Γ Distribution", - xlabel="Spanwise Position y/b", ylabel="Γ") - - ax_alpha_geo = Axis(fig[2, 1][2, 1], title="α Geometric", - xlabel="Spanwise Position y/b", ylabel="α (deg)") - ax_alpha_ac = Axis(fig[2, 1][2, 2], title="α at aero center", - xlabel="Spanwise Position y/b", ylabel="α (deg)") - ax_alpha_unc = Axis(fig[2, 1][2, 3], title="α Uncorrected", - xlabel="Spanwise Position y/b", ylabel="α (deg)") - - ax_fx = Axis(fig[2, 1][3, 1], title="Force x", - xlabel="Spanwise Position y/b", ylabel="Fx") - ax_fy = Axis(fig[2, 1][3, 2], title="Force y", - xlabel="Spanwise Position y/b", ylabel="Fy") - ax_fz = Axis(fig[2, 1][3, 3], title="Force z", - xlabel="Spanwise Position y/b", ylabel="Fz") - - cl_val = round(results["cl"], digits=2) - lines!(ax_cl, Vector(y_coords), Vector(results["cl_distribution"]), + aoa_span = round(angle_of_attack_for_spanwise_distribution, digits=1) + + ax_cl = Axis(fig[2, 1][1, 1], title="CL Distribution (α=$aoa_span)", + xlabel="Spanwise position y[m]", ylabel="CL") + ax_cd = Axis(fig[2, 1][1, 2], title="CD Distribution (α=$aoa_span)", + xlabel="Spanwise position y[m]", ylabel="CD") + ax_gamma = Axis(fig[2, 1][1, 3], title="Γ Distribution (α=$aoa_span)", + xlabel="Spanwise position y[m]", ylabel="Γ") + ax_alpha_geo = Axis(fig[2, 1][2, 1], title="α Geometric (α=$aoa_span)", + xlabel="Spanwise position y[m]", ylabel="α (deg)") + ax_alpha_ac = Axis(fig[2, 1][2, 2], title="α at 1/4c aero center (α=$aoa_span)", + xlabel="Spanwise position y[m]", ylabel="α (deg)") + ax_alpha_unc = Axis(fig[2, 1][2, 3], title="α at 3/4c uncorrected (α=$aoa_span)", + xlabel="Spanwise position y[m]", ylabel="α (deg)") + + ax_fx = Axis(fig[2, 1][3, 1], title="Force x (α=$aoa_span)", + xlabel="Spanwise position y[m]", ylabel="Fx") + ax_fy = Axis(fig[2, 1][3, 2], title="Force y(α=$aoa_span)", + xlabel="Spanwise position y[m]", ylabel="Fy") + ax_fz = Axis(fig[2, 1][3, 3], title="Force z (α=$aoa_span)", + xlabel="Spanwise position y[m]", ylabel="Fz") + + cl_val = round(results_spanwise["cl"], digits=2) + lines!(ax_cl, Vector(y_coords), Vector(results_spanwise["cl_distribution"]), label="$solver_label CL: $cl_val") axislegend(ax_cl, position=:lt) - cd_val = round(results["cd"], digits=2) - lines!(ax_cd, Vector(y_coords), Vector(results["cd_distribution"]), + cd_val = round(results_spanwise["cd"], digits=2) + lines!(ax_cd, Vector(y_coords), Vector(results_spanwise["cd_distribution"]), label="$solver_label CD: $cd_val") axislegend(ax_cd, position=:lt) - lines!(ax_gamma, Vector(y_coords), Vector(results["gamma_distribution"]), + lines!(ax_gamma, Vector(y_coords), Vector(results_spanwise["gamma_distribution"]), label=solver_label) axislegend(ax_gamma, position=:lt) - lines!(ax_alpha_geo, Vector(y_coords), Vector(results["alpha_geometric"]), + lines!(ax_alpha_geo, Vector(y_coords), rad2deg.(Vector(results_spanwise["alpha_geometric"])), label=solver_label) axislegend(ax_alpha_geo, position=:lt) - lines!(ax_alpha_ac, Vector(y_coords), Vector(results["alpha_at_ac"]), + lines!(ax_alpha_ac, Vector(y_coords), rad2deg.(Vector(results_spanwise["alpha_at_ac"])), label=solver_label) axislegend(ax_alpha_ac, position=:lt) lines!(ax_alpha_unc, Vector(y_coords), - Vector(results["alpha_uncorrected"]), label=solver_label) + rad2deg.(Vector(results_spanwise["alpha_uncorrected"])), label=solver_label) axislegend(ax_alpha_unc, position=:lt) + # force y-limits + ylims!(ax_alpha_geo, -0.25 * aoa_span, 1.1 * aoa_span) + + + force_axes = [ax_fx, ax_fy, ax_fz] components = ["x", "y", "z"] for (idx, (ax, comp)) in enumerate(zip(force_axes, components)) - forces = results["F_distribution"][idx, :] - total_force = round(results["F$comp"], digits=2) + forces = results_spanwise["F_distribution"][idx, :] + total_force = round(results_spanwise["F$comp"], digits=2) lines!(ax, Vector(y_coords), Vector(forces), label="$solver_label ΣF$comp: $total_force N") axislegend(ax, position=:lt) end # [2,2] Polars (2×2 grid) - polar_data, rey = generate_polar_data_makie( - solver, body_aero, angle_range; - angle_type, angle_of_attack=deg2rad(angle_of_attack), - side_slip=deg2rad(side_slip), v_a + polar_solver = compute_polar_with_cmy( + solver, + body_aero, + angle_range; + angle_type=angle_type, + angle_of_attack=angle_of_attack, + side_slip=side_slip, + v_a=v_a ) - label_with_re = "$solver_label Re = $(round(Int64, rey*1e-5))e5" + label_with_re = "$solver_label Re = $(round(Int64, first(polar_solver.rey)*1e-5))e5" + + # Load literature data (if any) + polar_series = [(polar_solver, label_with_re)] + if !isempty(literature_path_list) + for path in literature_path_list + data = readdlm(path, ',') + header_raw = string.(data[1, :]) + header = lowercase.(strip.(header_raw)) + alpha_idx = findfirst(x -> occursin("alpha", x) || occursin("aoa", x), header) + cl_idx = findfirst(x -> occursin("cl", x), header) + cd_idx = findfirst(x -> occursin("cd", x), header) + cs_idx = findfirst(x -> occursin("cs", x), header) + cmy_idx = findfirst(x -> occursin("cmy", x), header) + + parse_col(col) = begin + vals = Float64[] + for v in col + if v isa Real + push!(vals, Float64(v)) + else + s = strip(String(v)) + y = tryparse(Float64, s) + push!(vals, isnothing(y) ? NaN : y) + end + end + vals + end + + angles = parse_col(data[2:end, alpha_idx]) + cl_vals = parse_col(data[2:end, cl_idx]) + cd_vals = parse_col(data[2:end, cd_idx]) + cs_vals = cs_idx === nothing ? zeros(size(data, 1) - 1) : parse_col(data[2:end, cs_idx]) + cmy_vals = cmy_idx === nothing ? fill(NaN, length(angles)) : parse_col(data[2:end, cmy_idx]) + lit_label = splitext(basename(path))[1] + + push!(polar_series, ((angle=angles, cl=cl_vals, cd=cd_vals, cs=cs_vals, cmy=cmy_vals, rey=fill(NaN, length(angles))), lit_label)) + end + end ax_cl_polar = Axis(fig[2, 2][1, 1], title="CL vs $angle_type [°]", xlabel="$angle_type [°]", ylabel="CL") @@ -1166,21 +1282,21 @@ function VortexStepMethod.plot_combined_analysis( ax_polar = Axis(fig[2, 2][2, 2], title="CL vs CD", xlabel="CD", ylabel="CL") - scatterlines!(ax_cl_polar, polar_data[1], polar_data[2]; - label=label_with_re, marker=:star5, markersize=12) - axislegend(ax_cl_polar, position=:lt) - - scatterlines!(ax_cd_polar, polar_data[1], polar_data[3]; - label=label_with_re, marker=:star5, markersize=12) - axislegend(ax_cd_polar, position=:lt) + colors = Makie.wong_colors() + for (idx, (pd, lbl)) in enumerate(polar_series) + color = colors[mod1(idx, length(colors))] + marker = idx == 1 ? :star5 : :circle + markersize = idx == 1 ? 12 : 8 - scatterlines!(ax_cs_polar, polar_data[1], polar_data[4]; - label=label_with_re, marker=:star5, markersize=12) - axislegend(ax_cs_polar, position=:lt) - - scatterlines!(ax_polar, polar_data[3], polar_data[2]; - label=label_with_re, marker=:star5, markersize=12) - axislegend(ax_polar, position=:lt) + scatterlines!(ax_cl_polar, pd.angle, pd.cl; label=lbl, marker, markersize, color) + scatterlines!(ax_cd_polar, pd.angle, pd.cd; label=lbl, marker, markersize, color) + scatterlines!(ax_cs_polar, pd.angle, pd.cs; label=lbl, marker, markersize, color) + scatterlines!(ax_polar, pd.cd, pd.cl; label=lbl, marker, markersize, color) + end + # axislegend(ax_cl_polar, position=:lt) + # axislegend(ax_cd_polar, position=:lt) + axislegend(ax_cs_polar, position=:lb) + # axislegend(ax_polar, position=:lt) # Set column widths: left column wider for 3x3 grid colsize!(fig.layout, 1, Relative(0.6)) diff --git a/src/body_aerodynamics.jl b/src/body_aerodynamics.jl index b40be910..4e998ce3 100644 --- a/src/body_aerodynamics.jl +++ b/src/body_aerodynamics.jl @@ -597,11 +597,24 @@ function calculate_results( wing_span = body_aero.wings[1].span aspect_ratio_projected = wing_span^2 / projected_area - # Calculate geometric angle of attack - horizontal_direction = [1.0, 0.0, 0.0] - alpha_geometric = [rad2deg(acos(dot(panel.x_airf, horizontal_direction) / - (norm(panel.x_airf) * norm(horizontal_direction)))) - for panel in panels] + # Calculate geometric angle of attack relative to each panel's local axes (using prescribed freestream) + alpha_geometric = [ + begin + va_norm = norm(panel.va) + x_norm = norm(panel.x_airf) + z_norm = norm(panel.z_airf) + # Guard against zero-length vectors + if va_norm == 0 || x_norm == 0 || z_norm == 0 + NaN + else + v_unit = panel.va / va_norm + v_tangential = dot(panel.x_airf, -v_unit) / x_norm + v_normal = dot(panel.z_airf, -v_unit) / z_norm + pi + atan(v_normal, v_tangential) + end + end + for panel in panels + ] # Calculate Reynolds number max_chord = maximum(panel.chord for panel in panels) @@ -746,4 +759,3 @@ function set_va!(body_aero::BodyAerodynamics, settings::VSMSettings) set_va!(body_aero, va) end - diff --git a/src/settings.jl b/src/settings.jl index 9c6bd81f..1e718c94 100644 --- a/src/settings.jl +++ b/src/settings.jl @@ -107,10 +107,10 @@ function VSMSettings(filename; data_prefix=true) vsm_settings.solver_settings.aerodynamic_model_type = eval(Symbol(solver_data["aerodynamic_model_type"])) vsm_settings.solver_settings.type_initial_gamma_distribution = eval(Symbol(solver_data["type_initial_gamma_distribution"])) - # Set correct_aoa default based on model type if not explicitly provided - if !haskey(solver_data, "correct_aoa") - vsm_settings.solver_settings.correct_aoa = (vsm_settings.solver_settings.aerodynamic_model_type == VSM) - end + # # Set correct_aoa default based on model type if not explicitly provided + # if !haskey(solver_data, "correct_aoa") + # vsm_settings.solver_settings.correct_aoa = (vsm_settings.solver_settings.aerodynamic_model_type == VSM) + # end # Override with calculated totals vsm_settings.solver_settings.n_panels = n_panels From 15cd4bd0c016581456444f0d74d5c70a99ca2b71 Mon Sep 17 00:00:00 2001 From: jellepoland Date: Fri, 2 Jan 2026 16:16:18 +0100 Subject: [PATCH 55/86] added alpha_geometric_dist to the solver output, and updated example V3_kite to also test solve! output --- examples/V3_kite.jl | 207 +++++++++++++++++++++++++++++++++++++++++++- src/solver.jl | 29 ++++++- 2 files changed, 233 insertions(+), 3 deletions(-) diff --git a/examples/V3_kite.jl b/examples/V3_kite.jl index 45818095..709cf01b 100644 --- a/examples/V3_kite.jl +++ b/examples/V3_kite.jl @@ -1,6 +1,7 @@ using LinearAlgebra using VortexStepMethod using GLMakie +using DelimitedFiles PLOT = true USE_TEX = false @@ -57,7 +58,7 @@ USE_TEX = false # Solve and plot combined analysis results = VortexStepMethod.solve(solver, body_aero; log=true) -PLOT && plot_combined_analysis( +fig1 = plot_combined_analysis( solver, body_aero, results; @@ -69,10 +70,212 @@ PLOT && plot_combined_analysis( side_slip=sideslip_deg, v_a=wind_speed, title="TU Delft V3 Kite", - is_show=true, + is_show=false, use_tex=USE_TEX, angle_of_attack_for_spanwise_distribution=10.0, ) +scr1 = display(fig1) +wait(scr1) + + +# Polar sweep including CMy, using solve! and calculate_results +function compute_polar_with_cm( + solver, + body_aero, + angle_range; + angle_type::String="angle_of_attack", + angle_of_attack::Float64=0.0, + side_slip::Float64=0.0, + v_a::Float64=10.0 +) + n_angles = length(angle_range) + cl = zeros(n_angles) + cd = zeros(n_angles) + cs = zeros(n_angles) + cmy = fill(NaN, n_angles) + reynolds_number = zeros(n_angles) + + gamma_prev = solver.sol.gamma_distribution + for (i, angle_i) in enumerate(angle_range) + if angle_type == "angle_of_attack" + α = deg2rad(angle_i) + β = deg2rad(side_slip) + elseif angle_type == "side_slip" + α = deg2rad(angle_of_attack) + β = deg2rad(angle_i) + else + throw(ArgumentError("angle_type must be 'angle_of_attack' or 'side_slip'")) + end + + set_va!(body_aero, [cos(α) * cos(β), sin(β), sin(α)] * v_a) + solve!(solver, body_aero, gamma_prev; log=false) + gamma_prev = solver.sol.gamma_distribution + + results_local = calculate_results( + body_aero, + solver.lr.gamma_new, + zeros(MVec3), + solver.density, + solver.aerodynamic_model_type, + solver.core_radius_fraction, + solver.mu, + solver.lr.alpha_dist, + solver.lr.v_a_dist, + solver.sol._chord_dist, + solver.sol._x_airf_dist, + solver.sol._y_airf_dist, + solver.sol._z_airf_dist, + solver.sol._va_dist, + solver.br.va_norm_dist, + solver.br.va_unit_dist, + body_aero.panels, + solver.is_only_f_and_gamma_output; + correct_aoa=solver.correct_aoa + ) + + cl[i] = results_local["cl"] + cd[i] = results_local["cd"] + cs[i] = results_local["cs"] + cmy[i] = get(results_local, "cmy", NaN) + reynolds_number[i] = results_local["Rey"] + end + + return (angle=angle_range, cl=cl, cd=cd, cs=cs, cmy=cmy, rey=reynolds_number) +end + +function plot_polars_with_cmy( + solver_list, + body_aero_list, + label_list; + literature_path_list::Vector{String}=String[], + angle_range=range(-10, 40, step=1), + angle_type::String="angle_of_attack", + angle_of_attack::Float64=0.0, + side_slip::Float64=0.0, + v_a::Float64=10.0, + title::String="polar_with_cm", + fig_size::Tuple{Int,Int}=(1200, 800), + angle_xlim::Tuple{Real,Real}=(-10, 40) +) + total_cases = length(body_aero_list) + length(literature_path_list) + length(label_list) == total_cases || throw(ArgumentError("labels length ($(length(label_list))) must match number of cases ($total_cases)")) + length(solver_list) == length(body_aero_list) || throw(ArgumentError("solver_list length must match body_aero_list length")) + + polar_data_list = Vector{Any}() + labels_full = String[] + + # Computational cases + for (solver_i, body, lbl) in zip(solver_list, body_aero_list, label_list[1:length(solver_list)]) + pd = compute_polar_with_cm( + solver_i, + body, + angle_range; + angle_type=angle_type, + angle_of_attack=angle_of_attack, + side_slip=side_slip, + v_a=v_a + ) + @info "polar sample (solver)" label=lbl first_cl=pd.cl[1] first_cd=pd.cd[1] first_cs=pd.cs[1] first_cmy=pd.cmy[1] + push!(polar_data_list, pd) + re_tag = round(Int, first(pd.rey) * 1e-5) + push!(labels_full, "$(lbl) Re=$(re_tag)e5") + end + + # Literature cases + for (path, lbl) in zip(literature_path_list, label_list[length(solver_list)+1:end]) + data = readdlm(path, ',') + header_raw = string.(data[1, :]) + header = lowercase.(strip.(header_raw)) + alpha_idx = findfirst(x -> occursin("alpha", x) || occursin("aoa", x), header) + cl_idx = findfirst(x -> occursin("cl", x), header) + cd_idx = findfirst(x -> occursin("cd", x), header) + cs_idx = findfirst(x -> occursin("cs", x), header) + cmy_idx = findfirst(x -> occursin("cmy", x), header) + + parse_col(col) = begin + vals = Float64[] + for v in col + if v isa Real + push!(vals, Float64(v)) + else + s = strip(String(v)) + y = tryparse(Float64, s) + push!(vals, isnothing(y) ? NaN : y) + end + end + vals + end + + alpha_col = parse_col(data[2:end, alpha_idx]) + cl_col = parse_col(data[2:end, cl_idx]) + cd_col = parse_col(data[2:end, cd_idx]) + cs_col = cs_idx === nothing ? zeros(size(data, 1)-1) : parse_col(data[2:end, cs_idx]) + cmy_col = cmy_idx === nothing ? nothing : parse_col(data[2:end, cmy_idx]) + + push!(polar_data_list, (angle=alpha_col, cl=cl_col, cd=cd_col, cs=cs_col, cmy=cmy_col, rey=fill(NaN, length(alpha_col)))) + push!(labels_full, lbl) + end + + fig = Figure(size=fig_size) + Label(fig[0, :], title; fontsize=20, font=:bold) + + ax_cl = Axis(fig[1, 1], title="CL vs $angle_type [deg]", xlabel="$angle_type [deg]", ylabel="CL [-]") + ax_cd = Axis(fig[1, 2], title="CD vs $angle_type [deg]", xlabel="$angle_type [deg]", ylabel="CD [-]") + ax_cmy = Axis(fig[1, 3], title="CMy vs $angle_type [deg]", xlabel="$angle_type [deg]", ylabel="CMy [-]") + ax_cs = Axis(fig[2, 1], title="CS vs $angle_type [deg]", xlabel="$angle_type [deg]", ylabel="CS [-]") + ax_polar = Axis(fig[2, 2], title="CL vs CD", xlabel="CD [-]", ylabel="CL [-]") + + xlims!(ax_cl, angle_xlim...) + xlims!(ax_cd, angle_xlim...) + xlims!(ax_cmy, angle_xlim...) + xlims!(ax_cs, angle_xlim...) + + colors = Makie.wong_colors() + + for (idx, (pd, lbl)) in enumerate(zip(polar_data_list, labels_full)) + color = colors[mod1(idx, length(colors))] + + lines!(ax_cl, pd.angle, pd.cl; color, label=lbl) + scatter!(ax_cl, pd.angle, pd.cl; color, markersize=6) + + lines!(ax_cd, pd.angle, pd.cd; color, label=lbl) + scatter!(ax_cd, pd.angle, pd.cd; color, markersize=6) + + lines!(ax_cs, pd.angle, pd.cs; color, label=lbl) + scatter!(ax_cs, pd.angle, pd.cs; color, markersize=6) + + lines!(ax_polar, pd.cd, pd.cl; color, label=lbl) + scatter!(ax_polar, pd.cd, pd.cl; color, markersize=6) + + if pd.cmy !== nothing + cmy_vals = Float64.(pd.cmy) + if !all(isnan, cmy_vals) + lines!(ax_cmy, pd.angle, cmy_vals; color, label=lbl) + scatter!(ax_cmy, pd.angle, cmy_vals; color, markersize=6) + end + end + end + + Legend(fig[2, 3], ax_cl) + return fig +end + + +fig2 = plot_polars_with_cmy( + [solver], + [body_aero], + labels; + literature_path_list=literature_paths, + angle_range=range(-5, 40, step=1), + angle_type="angle_of_attack", + angle_of_attack=angle_of_attack_deg, + side_slip=sideslip_deg, + v_a=wind_speed, + title="Testing solve! on V3 kite", + angle_xlim=(-5, 40) +) +scr2 = display(fig2) +wait(scr2) nothing diff --git a/src/solver.jl b/src/solver.jl index 88e997a2..ced7297d 100644 --- a/src/solver.jl +++ b/src/solver.jl @@ -43,6 +43,7 @@ Struct for storing the solution of the [solve!](@ref) function. Must contain all ### end of private vectors width_dist::Vector{Float64} = zeros(P) alpha_dist::Vector{Float64} = zeros(P) + alpha_geometric_dist::Vector{Float64} = zeros(P) cl_dist::Vector{Float64} = zeros(P) cd_dist::Vector{Float64} = zeros(P) cm_dist::Vector{Float64} = zeros(P) @@ -208,6 +209,7 @@ function solve!(solver::Solver, body_aero::BodyAerodynamics, gamma_distribution= converged = solver.lr.converged alpha_dist = solver.lr.alpha_dist alpha_corrected = solver.sol.alpha_dist + alpha_geometric_dist = solver.sol.alpha_geometric_dist v_a_dist = solver.lr.v_a_dist panels = body_aero.panels @@ -224,6 +226,28 @@ function solve!(solver::Solver, body_aero::BodyAerodynamics, gamma_distribution= cl_dist[i] = calculate_cl(panel, alpha_dist[i]) cd_dist[i], cm_dist[i] = calculate_cd_cm(panel, alpha_dist[i]) width_dist[i] = panel.width + + # Geometric AoA using panel-local axes and prescribed freestream + # @views makes slices like solver.sol._va_dist[i, :] return views instead of copies. + # Without it, each [...] would allocate a new array; with it, you reuse a lightweight + # window into the original array, which cuts allocations in this tight loop. + @views begin + va_panel = solver.sol._va_dist[i, :] + x_airf = solver.sol._x_airf_dist[i, :] + z_airf = solver.sol._z_airf_dist[i, :] + va_norm = norm(va_panel) + x_norm = norm(x_airf) + z_norm = norm(z_airf) + if va_norm == 0 || x_norm == 0 || z_norm == 0 + alpha_geometric_dist[i] = NaN + else + v_unit = va_panel / va_norm + v_tangential = dot(x_airf, -v_unit) / x_norm + v_normal = dot(z_airf, -v_unit) / z_norm + alpha_geometric_dist[i] = pi + atan(v_normal, v_tangential) + end + end + end # create an alias for the three vertical output vectors @@ -465,6 +489,10 @@ function solve(solver::Solver, body_aero::BodyAerodynamics, gamma_distribution=n solver.is_only_f_and_gamma_output; correct_aoa=solver.correct_aoa ) + # Attach geometric AoA (already computed in calculate_results) to solver.sol + if haskey(results, "alpha_geometric") + solver.sol.alpha_geometric_dist .= results["alpha_geometric"] + end return results end @@ -885,4 +913,3 @@ function linearize(solver::Solver, body_aero::BodyAerodynamics, y::Vector{T}; calc_results!(results, y) return jac, results end - From f2b85b81ae130b311adace46f8ba6e933e67ba7a Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Fri, 9 Jan 2026 00:05:00 +0100 Subject: [PATCH 56/86] Add option to disable sort --- src/yaml_geometry.jl | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/yaml_geometry.jl b/src/yaml_geometry.jl index e6c39514..6c9accab 100644 --- a/src/yaml_geometry.jl +++ b/src/yaml_geometry.jl @@ -186,7 +186,8 @@ function Wing( spanwise_distribution=LINEAR, spanwise_direction=[0.0, 1.0, 0.0], remove_nan=true, - prn=false + prn=false, + sort_sections=true ) !isapprox(spanwise_direction, [0.0, 1.0, 0.0]) && throw(ArgumentError("Spanwise direction has to be [0.0, 1.0, 0.0], not $spanwise_direction")) @@ -262,7 +263,7 @@ function Wing( add_section!(wing, le_coord, te_coord, aero_model, aero_data) end - refine!(wing) + refine!(wing; sort_sections) return wing end @@ -296,7 +297,7 @@ wing = Wing(settings) # - obj_file + dat_file # OBJ-based ``` """ -function Wing(settings::VSMSettings) +function Wing(settings::VSMSettings; sort_sections::Bool=true) wing_settings = settings.wings[1] # Check which geometry format to use @@ -327,10 +328,11 @@ function Wing(settings::VSMSettings) Wing(wing_settings.geometry_file; n_panels=wing_settings.n_panels, spanwise_distribution=wing_settings.spanwise_panel_distribution, - remove_nan=wing_settings.remove_nan + remove_nan=wing_settings.remove_nan, + sort_sections ) elseif has_obj && has_dat - # Use ObjWing constructor + # Use ObjWing constructor (ObjWing doesn't sort sections internally) ObjWing( wing_settings.obj_file, wing_settings.dat_file; From 96a8e95b790e8999bcea60e71906bcd8fb734c51 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Fri, 9 Jan 2026 00:05:57 +0100 Subject: [PATCH 57/86] Flat extrapolate --- src/panel.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/panel.jl b/src/panel.jl index ba2e2448..d139857c 100644 --- a/src/panel.jl +++ b/src/panel.jl @@ -1,8 +1,8 @@ # static types for interpolations const I1 = Interpolations.FilledExtrapolation{Float64, 1, Interpolations.GriddedInterpolation{Float64, 1, Vector{Float64}, Interpolations.Gridded{Interpolations.Linear{Interpolations.Throw{Interpolations.OnGrid}}}, Tuple{Vector{Float64}}}, Interpolations.Gridded{Interpolations.Linear{Interpolations.Throw{Interpolations.OnGrid}}}, Float64} -const I2 = Interpolations.Extrapolation{Float64, 1, Interpolations.GriddedInterpolation{Float64, 1, Vector{Float64}, Interpolations.Gridded{Interpolations.Linear{Interpolations.Throw{Interpolations.OnGrid}}}, Tuple{Vector{Float64}}}, Interpolations.Gridded{Interpolations.Linear{Interpolations.Throw{Interpolations.OnGrid}}}, Interpolations.Line{Nothing}} +const I2 = Interpolations.Extrapolation{Float64, 1, Interpolations.GriddedInterpolation{Float64, 1, Vector{Float64}, Interpolations.Gridded{Interpolations.Linear{Interpolations.Throw{Interpolations.OnGrid}}}, Tuple{Vector{Float64}}}, Interpolations.Gridded{Interpolations.Linear{Interpolations.Throw{Interpolations.OnGrid}}}, Interpolations.Flat{Nothing}} const I3 = Interpolations.FilledExtrapolation{Float64, 2, Interpolations.GriddedInterpolation{Float64, 2, Matrix{Float64}, Interpolations.Gridded{Interpolations.Linear{Interpolations.Throw{Interpolations.OnGrid}}}, Tuple{Vector{Float64}, Vector{Float64}}}, Interpolations.Gridded{Interpolations.Linear{Interpolations.Throw{Interpolations.OnGrid}}}, Float64} -const I4 = Interpolations.Extrapolation{Float64, 2, Interpolations.GriddedInterpolation{Float64, 2, Matrix{Float64}, Interpolations.Gridded{Interpolations.Linear{Interpolations.Throw{Interpolations.OnGrid}}}, Tuple{Vector{Float64}, Vector{Float64}}}, Interpolations.Gridded{Interpolations.Linear{Interpolations.Throw{Interpolations.OnGrid}}}, Interpolations.Line{Nothing}} +const I4 = Interpolations.Extrapolation{Float64, 2, Interpolations.GriddedInterpolation{Float64, 2, Matrix{Float64}, Interpolations.Gridded{Interpolations.Linear{Interpolations.Throw{Interpolations.OnGrid}}}, Tuple{Vector{Float64}, Vector{Float64}}}, Interpolations.Gridded{Interpolations.Linear{Interpolations.Throw{Interpolations.OnGrid}}}, Interpolations.Flat{Nothing}} """ @with_kw mutable struct Panel @@ -141,7 +141,7 @@ function init_aero!( end if remove_nan - extrapolation_bc = Line() + extrapolation_bc = Flat() else extrapolation_bc = NaN end From c65858c0ff8721f44a676408e1c14fb5ecde2967 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sat, 10 Jan 2026 13:21:03 +0100 Subject: [PATCH 58/86] Extrapolate lift flat drag line --- src/panel.jl | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/panel.jl b/src/panel.jl index d139857c..b630e4f1 100644 --- a/src/panel.jl +++ b/src/panel.jl @@ -3,6 +3,9 @@ const I1 = Interpolations.FilledExtrapolation{Float64, 1, Interpolations.Gridded const I2 = Interpolations.Extrapolation{Float64, 1, Interpolations.GriddedInterpolation{Float64, 1, Vector{Float64}, Interpolations.Gridded{Interpolations.Linear{Interpolations.Throw{Interpolations.OnGrid}}}, Tuple{Vector{Float64}}}, Interpolations.Gridded{Interpolations.Linear{Interpolations.Throw{Interpolations.OnGrid}}}, Interpolations.Flat{Nothing}} const I3 = Interpolations.FilledExtrapolation{Float64, 2, Interpolations.GriddedInterpolation{Float64, 2, Matrix{Float64}, Interpolations.Gridded{Interpolations.Linear{Interpolations.Throw{Interpolations.OnGrid}}}, Tuple{Vector{Float64}, Vector{Float64}}}, Interpolations.Gridded{Interpolations.Linear{Interpolations.Throw{Interpolations.OnGrid}}}, Float64} const I4 = Interpolations.Extrapolation{Float64, 2, Interpolations.GriddedInterpolation{Float64, 2, Matrix{Float64}, Interpolations.Gridded{Interpolations.Linear{Interpolations.Throw{Interpolations.OnGrid}}}, Tuple{Vector{Float64}, Vector{Float64}}}, Interpolations.Gridded{Interpolations.Linear{Interpolations.Throw{Interpolations.OnGrid}}}, Interpolations.Flat{Nothing}} +# Line extrapolation types for cd +const I5 = Interpolations.Extrapolation{Float64, 1, Interpolations.GriddedInterpolation{Float64, 1, Vector{Float64}, Interpolations.Gridded{Interpolations.Linear{Interpolations.Throw{Interpolations.OnGrid}}}, Tuple{Vector{Float64}}}, Interpolations.Gridded{Interpolations.Linear{Interpolations.Throw{Interpolations.OnGrid}}}, Interpolations.Line{Nothing}} +const I6 = Interpolations.Extrapolation{Float64, 2, Interpolations.GriddedInterpolation{Float64, 2, Matrix{Float64}, Interpolations.Gridded{Interpolations.Linear{Interpolations.Throw{Interpolations.OnGrid}}}, Tuple{Vector{Float64}, Vector{Float64}}}, Interpolations.Gridded{Interpolations.Linear{Interpolations.Throw{Interpolations.OnGrid}}}, Interpolations.Line{Nothing}} """ @with_kw mutable struct Panel @@ -53,7 +56,7 @@ Represents a panel in a vortex step method simulation. All points and vectors ar cd_coeffs::Vector{Float64} = zeros(Float64, 3) cm_coeffs::Vector{Float64} = zeros(Float64, 3) cl_interp::Union{Nothing, I1, I2, I3, I4} = nothing - cd_interp::Union{Nothing, I1, I2, I3, I4} = nothing + cd_interp::Union{Nothing, I1, I2, I3, I4, I5, I6} = nothing cm_interp::Union{Nothing, I1, I2, I3, I4} = nothing aero_center::MVec3 = zeros(MVec3) control_point::MVec3 = zeros(MVec3) @@ -141,9 +144,11 @@ function init_aero!( end if remove_nan - extrapolation_bc = Flat() + extrap_flat = Flat() + extrap_line = Line() else - extrapolation_bc = NaN + extrap_flat = NaN + extrap_line = NaN end if panel.aero_model == POLAR_VECTORS @@ -156,9 +161,9 @@ function init_aero!( ) alphas = Vector{Float64}(aero_1[1]) - panel.cl_interp = linear_interpolation(alphas, polar_data[1]; extrapolation_bc) - panel.cd_interp = linear_interpolation(alphas, polar_data[2]; extrapolation_bc) - panel.cm_interp = linear_interpolation(alphas, polar_data[3]; extrapolation_bc) + panel.cl_interp = linear_interpolation(alphas, polar_data[1]; extrapolation_bc=extrap_flat) + panel.cd_interp = linear_interpolation(alphas, polar_data[2]; extrapolation_bc=extrap_line) + panel.cm_interp = linear_interpolation(alphas, polar_data[3]; extrapolation_bc=extrap_flat) elseif panel.aero_model == POLAR_MATRICES !all(isapprox.(aero_1[1], aero_2[1])) && @error "Make sure you use the same alpha range for all your interpolations." @@ -172,9 +177,9 @@ function init_aero!( alphas = Vector{Float64}(aero_1[1]) deltas = Vector{Float64}(aero_1[2]) - panel.cl_interp = linear_interpolation((alphas, deltas), polar_data[1]; extrapolation_bc) - panel.cd_interp = linear_interpolation((alphas, deltas), polar_data[2]; extrapolation_bc) - panel.cm_interp = linear_interpolation((alphas, deltas), polar_data[3]; extrapolation_bc) + panel.cl_interp = linear_interpolation((alphas, deltas), polar_data[1]; extrapolation_bc=extrap_flat) + panel.cd_interp = linear_interpolation((alphas, deltas), polar_data[2]; extrapolation_bc=extrap_line) + panel.cm_interp = linear_interpolation((alphas, deltas), polar_data[3]; extrapolation_bc=extrap_flat) else throw(ArgumentError("Polar data in wrong format: $aero_1")) end From 8cc302675b903f45c373aa1c64c75e51c29f6ae4 Mon Sep 17 00:00:00 2001 From: 1-Bart-1 Date: Sun, 11 Jan 2026 17:57:29 +0100 Subject: [PATCH 59/86] Working kulfan fit --- Project.toml | 4 + data/neuralfoil_weights/nn-large.npz | Bin 0 -> 296154 bytes data/neuralfoil_weights/nn-medium.npz | Bin 0 -> 103467 bytes data/neuralfoil_weights/nn-small.npz | Bin 0 -> 87420 bytes data/neuralfoil_weights/nn-xlarge.npz | Bin 0 -> 358165 bytes data/neuralfoil_weights/nn-xsmall.npz | Bin 0 -> 60435 bytes data/neuralfoil_weights/nn-xxlarge.npz | Bin 0 -> 1211667 bytes data/neuralfoil_weights/nn-xxsmall.npz | Bin 0 -> 51064 bytes data/neuralfoil_weights/nn-xxxlarge.npz | Bin 0 -> 5356191 bytes .../scaled_input_distribution.npz | Bin 0 -> 7696 bytes data/ram_air_kite/polars_neuralfoil/1.csv | 62 +++ data/ram_air_kite/polars_neuralfoil/10.csv | 62 +++ data/ram_air_kite/polars_neuralfoil/2.csv | 62 +++ data/ram_air_kite/polars_neuralfoil/3.csv | 62 +++ data/ram_air_kite/polars_neuralfoil/4.csv | 62 +++ data/ram_air_kite/polars_neuralfoil/5.csv | 62 +++ data/ram_air_kite/polars_neuralfoil/6.csv | 62 +++ data/ram_air_kite/polars_neuralfoil/7.csv | 62 +++ data/ram_air_kite/polars_neuralfoil/8.csv | 62 +++ data/ram_air_kite/polars_neuralfoil/9.csv | 62 +++ examples/neuralfoil_polars.jl | 28 ++ ext/VortexStepMethodMakieExt.jl | 168 +++++++- src/VortexStepMethod.jl | 17 +- src/kulfan.jl | 255 ++++++++++++ src/neuralfoil.jl | 362 ++++++++++++++++ src/obj_slice.jl | 392 ++++++++++++++++++ src/polar_generation.jl | 195 +++++++++ 27 files changed, 2039 insertions(+), 2 deletions(-) create mode 100644 data/neuralfoil_weights/nn-large.npz create mode 100644 data/neuralfoil_weights/nn-medium.npz create mode 100644 data/neuralfoil_weights/nn-small.npz create mode 100644 data/neuralfoil_weights/nn-xlarge.npz create mode 100644 data/neuralfoil_weights/nn-xsmall.npz create mode 100644 data/neuralfoil_weights/nn-xxlarge.npz create mode 100644 data/neuralfoil_weights/nn-xxsmall.npz create mode 100644 data/neuralfoil_weights/nn-xxxlarge.npz create mode 100644 data/neuralfoil_weights/scaled_input_distribution.npz create mode 100644 data/ram_air_kite/polars_neuralfoil/1.csv create mode 100644 data/ram_air_kite/polars_neuralfoil/10.csv create mode 100644 data/ram_air_kite/polars_neuralfoil/2.csv create mode 100644 data/ram_air_kite/polars_neuralfoil/3.csv create mode 100644 data/ram_air_kite/polars_neuralfoil/4.csv create mode 100644 data/ram_air_kite/polars_neuralfoil/5.csv create mode 100644 data/ram_air_kite/polars_neuralfoil/6.csv create mode 100644 data/ram_air_kite/polars_neuralfoil/7.csv create mode 100644 data/ram_air_kite/polars_neuralfoil/8.csv create mode 100644 data/ram_air_kite/polars_neuralfoil/9.csv create mode 100644 examples/neuralfoil_polars.jl create mode 100644 src/kulfan.jl create mode 100644 src/neuralfoil.jl create mode 100644 src/obj_slice.jl create mode 100644 src/polar_generation.jl diff --git a/Project.toml b/Project.toml index 7609394f..ab5c82fb 100644 --- a/Project.toml +++ b/Project.toml @@ -15,8 +15,10 @@ LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" Measures = "442fdcdd-2543-5da2-b0f3-8c86c306513e" NonlinearSolve = "8913a72c-1f9b-4ce2-8d82-65094dcecaec" +NPZ = "15e1cf62-19b3-5cfa-8e77-841668bca605" Parameters = "d96e819e-fc66-5662-9728-84c9c7592b0a" Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" +Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" PreallocationTools = "d236fae5-4411-538c-8e31-a6e3d9e00b46" PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a" RecursiveArrayTools = "731186ca-8d62-57ce-b412-fbd966d074cd" @@ -51,8 +53,10 @@ Logging = "1" Makie = "0.24.6" Measures = "0.3" NonlinearSolve = "4.8.0" +NPZ = "0.4" Parameters = "0.12" Pkg = "1" +Printf = "1" PreallocationTools = "0.4.31" PrecompileTools = "1.2.1" RecursiveArrayTools = "3 - 3.36.0" diff --git a/data/neuralfoil_weights/nn-large.npz b/data/neuralfoil_weights/nn-large.npz new file mode 100644 index 0000000000000000000000000000000000000000..58817d3c8d7d217f5db4dad2339f21dce75f3c96 GIT binary patch literal 296154 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 literal 0 HcmV?d00001 diff --git a/data/neuralfoil_weights/nn-medium.npz b/data/neuralfoil_weights/nn-medium.npz new file mode 100644 index 0000000000000000000000000000000000000000..9e5aa10c56a98d95c3dba12efec24adc2bf2889e GIT binary patch literal 103467 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
wETLpbYS%{N?r!#|$tAOlZKqoaF|hL}`G2=mLQ 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 D@Po!n literal 0 HcmV?d00001 diff --git a/data/neuralfoil_weights/nn-small.npz b/data/neuralfoil_weights/nn-small.npz new file mode 100644 index 0000000000000000000000000000000000000000..8e28f1d6e7574ef613b87615acad05fb5f20d9d6 GIT binary patch literal 87420 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�?)vexh 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�V1hbs)=`q+<8%GNyNZ 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 Jtb2Du`wzSgpUVIM literal 0 HcmV?d00001 diff --git a/data/neuralfoil_weights/nn-xlarge.npz b/data/neuralfoil_weights/nn-xlarge.npz new file mode 100644 index 0000000000000000000000000000000000000000..def69359a425229d0c69d4d0f36edbe7bbf22e27 GIT binary patch literal 358165 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 z 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 literal 0 HcmV?d00001 diff --git a/data/neuralfoil_weights/nn-xsmall.npz b/data/neuralfoil_weights/nn-xsmall.npz new file mode 100644 index 0000000000000000000000000000000000000000..29a131a3315e107df705958d1a528f3c7219274b GIT binary patch literal 60435 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

  • -*D`YL*1!0oKOq5@QkV-e`9xz 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