From fc87bda21e3bf7892f1bfeb8e0f3be30280fb43a Mon Sep 17 00:00:00 2001 From: 1-Bort-1 <323661610+1-Bort-1@users.noreply.github.com> Date: Mon, 21 Sep 2026 13:59:29 +0200 Subject: [PATCH 1/4] Rename the public apparent-wind API to va, va_vec and va_dist body_aero.va -> va_vec (field _va -> va_vec), va= -> va_vec= on BodyAerodynamics and reinit!, Panel.va -> va_vec, VSMSolution._va_dist -> va_vec_dist, va_unrefined_dist -> va_vec_unrefined_dist, BaseResult.va_norm_dist -> va_dist, v_a_dist -> v_rel_dist, SemiInfiniteFilament.vel_mag -> va, v_a= -> va= on the plot functions, linearize va_idxs= -> va_vec_idxs=, the "va_ref" result key -> "va_ref_vec", and the settings keys condition.wind_speed and airfoil.v_app -> va. Co-Authored-By: Claude Opus 5 --- data/TUDELFT_V3_KITE/vsm_settings.yaml | 2 +- data/TUDELFT_V3_KITE/vsm_settings_coarse.yaml | 2 +- data/pyramid_model/vsm_settings.yaml | 2 +- docs/src/examples.md | 2 +- docs/src/settings.md | 6 +- examples/V3_kite.jl | 8 +- examples/V3_neuralfoil.jl | 2 +- examples/billowing.jl | 6 +- examples/linearize_check.jl | 8 +- examples/obj_to_yaml_kite.jl | 2 +- examples/pyramid_model.jl | 6 +- examples/ram_air_kite.jl | 2 +- examples/rectangular_wing.jl | 2 +- examples/stall_model.jl | 2 +- ext/VortexStepMethodMakieExt.jl | 24 +++--- mwes/mwe_01.jl | 2 +- mwes/mwe_warntype.jl | 2 +- src/VortexStepMethod.jl | 4 +- src/body_aerodynamics.jl | 82 +++++++++---------- src/filament.jl | 6 +- src/panel.jl | 10 +-- src/settings.jl | 6 +- src/settings_adapters.jl | 4 +- src/solver.jl | 71 ++++++++-------- src/stability.jl | 38 ++++----- test/bench.jl | 10 +-- test/body_aerodynamics/complete_settings.yaml | 2 +- .../test_body_aerodynamics.jl | 35 ++++---- test/body_aerodynamics/test_results.jl | 6 +- test/filament/test_semi_infinite_filament.jl | 22 ++--- test/panel/test_panel.jl | 6 +- test/plotting/test_plotting.jl | 8 +- test/settings/basic_llt.yaml | 2 +- test/settings/basic_vsm.yaml | 2 +- test/settings/test_settings.jl | 2 +- test/solver/solver_settings.yaml | 2 +- test/solver/test_flow_curvature.jl | 2 +- test/solver/test_forwarddiff.jl | 10 +-- test/solver/test_solver.jl | 10 +-- test/solver/test_stability.jl | 34 ++++---- test/solver/test_unrefined_dist.jl | 6 +- test/solver/test_viscous_drag_correction.jl | 4 +- test/test_data_utils.jl | 6 +- test/thesis_oriol_cayon.jl | 8 +- test/verification/test_verification.jl | 34 ++++---- .../test_yaml_wing_deformation.jl | 2 +- 46 files changed, 257 insertions(+), 257 deletions(-) diff --git a/data/TUDELFT_V3_KITE/vsm_settings.yaml b/data/TUDELFT_V3_KITE/vsm_settings.yaml index 86683aa2..5a94cf62 100644 --- a/data/TUDELFT_V3_KITE/vsm_settings.yaml +++ b/data/TUDELFT_V3_KITE/vsm_settings.yaml @@ -34,7 +34,7 @@ # Define the flight state for the aerodynamic analysis condition: - wind_speed: 2.82 # [m/s] Free stream velocity magnitude + va: 2.82 # [m/s] apparent wind speed alpha: 7.4 # [°] Angle of attack (pitch angle relative to flow) beta: 0.0 # [°] Sideslip angle (yaw angle relative to flow) yaw_rate: 0.0 # [°/s] Yaw rate (for dynamic analysis, 0 for static) diff --git a/data/TUDELFT_V3_KITE/vsm_settings_coarse.yaml b/data/TUDELFT_V3_KITE/vsm_settings_coarse.yaml index 1e6f80bb..fef206f2 100644 --- a/data/TUDELFT_V3_KITE/vsm_settings_coarse.yaml +++ b/data/TUDELFT_V3_KITE/vsm_settings_coarse.yaml @@ -36,7 +36,7 @@ # Define the flight state for the aerodynamic analysis condition: - wind_speed: 10.0 # [m/s] Free stream velocity magnitude + va: 10.0 # [m/s] apparent wind speed alpha: 0.0 # [°] Angle of attack (pitch angle relative to flow) beta: 0.0 # [°] Sideslip angle (yaw angle relative to flow) yaw_rate: 0.0 # [°/s] Yaw rate (for dynamic analysis, 0 for static) diff --git a/data/pyramid_model/vsm_settings.yaml b/data/pyramid_model/vsm_settings.yaml index c3db7fee..7e21494a 100644 --- a/data/pyramid_model/vsm_settings.yaml +++ b/data/pyramid_model/vsm_settings.yaml @@ -34,7 +34,7 @@ # Define the flight state for the aerodynamic analysis condition: - wind_speed: 10.0 # [m/s] Free stream velocity magnitude + va: 10.0 # [m/s] apparent wind speed alpha: 5.0 # [°] Angle of attack (pitch angle relative to flow) beta: 0.0 # [°] Sideslip angle (yaw angle relative to flow) yaw_rate: 0.0 # [°/s] Yaw rate (for dynamic analysis, 0 for static) diff --git a/docs/src/examples.md b/docs/src/examples.md index 14794e24..03cc167c 100644 --- a/docs/src/examples.md +++ b/docs/src/examples.md @@ -118,7 +118,7 @@ julia> plot_combined_analysis( solver_label=["LLT", "VSM"], angle_range=angle_range, angle_type="angle_of_attack", - v_a=va, + va=va, title="Rectangular Wing", is_show=true, ) diff --git a/docs/src/settings.md b/docs/src/settings.md index ab17506b..3c6d0573 100644 --- a/docs/src/settings.md +++ b/docs/src/settings.md @@ -29,7 +29,7 @@ values shown are those defaults, and the docstrings linked below carry the rest. ```yaml condition: - wind_speed: 10.0 # free-stream velocity magnitude [m/s] + va: 10.0 # apparent wind speed [m/s] alpha: 5.0 # angle of attack [°] beta: 0.0 # sideslip angle [°] yaw_rate: 0.0 # turn rate about the body z axis [°/s] @@ -67,7 +67,7 @@ wings: delta_range: [-40, 10, 40] # flap-deflection sweep [°]; null for no flap sweep # angles off the reference angle a live polar is re-solved at [°] live_offsets: [-12, -9, -6, -3, 0, 3, 6, 9, 12] - v_app: 25.0 # apparent wind the Reynolds number is taken at [m/s] + va: 25.0 # apparent wind the Reynolds number is taken at [m/s] chord_ref: 1.0 # reference (maximum panel) chord [m] table_format: arrow # per-node table format: csv or arrow @@ -111,4 +111,4 @@ One block answers for both the tables a mesh is sliced into and the live polars deformed section is re-solved on, so the two cannot be generated at different transition settings or off different networks. [`alpha_range`](@ref), [`delta_range`](@ref) and [`reynolds`](@ref) turn the sweeps and the -`density * v_app * chord_ref / mu` reference into what the polar generator takes. +`density * va * chord_ref / mu` reference into what the polar generator takes. diff --git a/examples/V3_kite.jl b/examples/V3_kite.jl index 443c88c1..b29350f8 100644 --- a/examples/V3_kite.jl +++ b/examples/V3_kite.jl @@ -94,7 +94,7 @@ labels = [solver_labels; "WindTunnel Re=5e5"]] #with struts beta_labels = [solver_labels; ["Wind Tunnel Re=5e5 beta sweep alpha=7.4"]] -wind_speed = settings.condition.wind_speed +va = settings.condition.va angle_of_attack_deg = settings.condition.alpha sideslip_deg = settings.condition.beta yaw_rate = settings.condition.yaw_rate @@ -111,7 +111,7 @@ PLOT && plot_polars( angle_type="angle_of_attack", angle_of_attack=angle_of_attack_deg, side_slip=sideslip_deg, - v_a=wind_speed, + va=va, title="$(wing.n_panels)_panels_$(wing.spanwise_distribution)_from_yaml_settings", save_path=OUTPUT_DIR, is_save=false || SAVE_ALL, @@ -141,7 +141,7 @@ 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))_va_$(round(wind_speed, digits=1))", + title="CAD_spanwise_distributions_alpha_$(round(angle_of_attack_deg, digits=1))_delta_$(round(sideslip_deg, digits=1))_yaw_$(round(yaw_rate, digits=1))_va_$(round(va, digits=1))", save_path=OUTPUT_DIR, is_save=false || SAVE_ALL, is_show=true, @@ -158,7 +158,7 @@ PLOT && plot_polars( angle_type="side_slip", angle_of_attack=angle_of_attack_deg, side_slip=sideslip_deg, - v_a=wind_speed, + va=va, title="beta sweep", show_moments=true, save_path=OUTPUT_DIR, diff --git a/examples/V3_neuralfoil.jl b/examples/V3_neuralfoil.jl index 245a2087..12aa4009 100644 --- a/examples/V3_neuralfoil.jl +++ b/examples/V3_neuralfoil.jl @@ -109,7 +109,7 @@ fig = plot_polars( "Wind tunnel (Poland 2025)"]; literature_path_list=literature_paths, angle_range, - v_a=va, + va=va, title="TU Delft V3 Kite: CFD vs NeuralFoil (Re=$RE)", is_save=false, ) diff --git a/examples/billowing.jl b/examples/billowing.jl index d78b8831..74a8b781 100644 --- a/examples/billowing.jl +++ b/examples/billowing.jl @@ -83,13 +83,13 @@ solver_flat = Solver(settings; reference_point=[0.422646, 0.0, 9.3667]) solver_bill = Solver(settings; reference_point=[0.422646, 0.0, 9.3667]) # --- Set flight conditions --- -wind_speed = settings.condition.wind_speed +va = settings.condition.va angle_of_attack_deg = 10.0 sideslip_deg = settings.condition.beta α0 = deg2rad(angle_of_attack_deg) β0 = deg2rad(sideslip_deg) -va_vec = apparent_wind(α0, β0, wind_speed) +va_vec = apparent_wind(α0, β0, va) set_va!(body_aero_flat, va_vec) set_va!(body_aero_bill, va_vec) @@ -141,7 +141,7 @@ if PLOT angle_type="angle_of_attack", angle_of_attack=angle_of_attack_deg, side_slip=sideslip_deg, - v_a=wind_speed, + va=va, title="V3 Kite flat vs billowing $(BILLOWING_PCT)%", save_path=OUTPUT_DIR, is_save=false || SAVE_ALL, diff --git a/examples/linearize_check.jl b/examples/linearize_check.jl index 4117cf30..00a610a0 100644 --- a/examples/linearize_check.jl +++ b/examples/linearize_check.jl @@ -40,7 +40,7 @@ omega_b_0 = zeros(3) theta_0 = zeros(n_unrefined) theta_idxs = 1:n_unrefined -va_idxs = (n_unrefined + 1):(n_unrefined + 3) +va_vec_idxs = (n_unrefined + 1):(n_unrefined + 3) omega_idxs = (n_unrefined + 4):(n_unrefined + 6) y0 = [theta_0; va_vec_b_0; omega_b_0] @@ -48,7 +48,7 @@ y0 = [theta_0; va_vec_b_0; omega_b_0] t_fd = @elapsed begin jac_fd, x0_fd, conv_fd = linearize( solver, body_aero, y0; - theta_idxs, va_idxs, omega_idxs, + theta_idxs, va_vec_idxs, omega_idxs, aero_coeffs=true, backend=AutoFiniteDiff(absstep=1e-5, relstep=1e-5), ) @@ -59,7 +59,7 @@ conv_fd || @warn "FiniteDiff linearize did not converge at operating point" t_fwd = @elapsed begin jac_fwd, x0_fwd, conv_fwd = linearize( solver, body_aero, y0; - theta_idxs, va_idxs, omega_idxs, + theta_idxs, va_vec_idxs, omega_idxs, aero_coeffs=true, backend=AutoForwardDiff(), ) @@ -105,7 +105,7 @@ last_theta = fill(NaN, n_unrefined) function solve_at!(y) theta = y[theta_idxs] - va_vec = y[va_idxs] + va_vec = y[va_vec_idxs] omega = y[omega_idxs] if !all(theta .== last_theta) unrefined_deform!(wing, theta, nothing; smooth=false) diff --git a/examples/obj_to_yaml_kite.jl b/examples/obj_to_yaml_kite.jl index 3856533b..13f2db61 100644 --- a/examples/obj_to_yaml_kite.jl +++ b/examples/obj_to_yaml_kite.jl @@ -86,7 +86,7 @@ if PLOT plot_section_polars(body_aero; panels=[1, 10], is_show=true) plot_polars([solver], [body_aero], ["VSM (NeuralFoil polars from .obj)"]; - angle_range=range(-5, 20, length=26), v_a=va, + angle_range=range(-5, 20, length=26), va=va, title="Ram air kite: obj_to_yaml route", is_save=false, use_tex=USE_TEX) end diff --git a/examples/pyramid_model.jl b/examples/pyramid_model.jl index 604ee950..cd19b268 100644 --- a/examples/pyramid_model.jl +++ b/examples/pyramid_model.jl @@ -20,7 +20,7 @@ solver = Solver(vsm_settings) set_va!(body_aero, vsm_settings) # Extract values for plotting (optional - for reference) -wind_speed = vsm_settings.condition.wind_speed +va = vsm_settings.condition.va angle_of_attack_deg = vsm_settings.condition.alpha sideslip_deg = vsm_settings.condition.beta yaw_rate = vsm_settings.condition.yaw_rate @@ -43,7 +43,7 @@ PLOT && plot_polars( angle_type="angle_of_attack", angle_of_attack=angle_of_attack_deg, side_slip=sideslip_deg, - v_a=wind_speed, + va=va, title="$(wing.n_panels)_panels_$(wing.spanwise_distribution)_pyramid_model", save_path=OUTPUT_DIR, is_save=false || SAVE_ALL, @@ -70,7 +70,7 @@ 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))_va_$(round(wind_speed, digits=1))", + title="pyramid_spanwise_distributions_alpha_$(round(angle_of_attack_deg, digits=1))_delta_$(round(sideslip_deg, digits=1))_yaw_$(round(yaw_rate, digits=1))_va_$(round(va, digits=1))", save_path=OUTPUT_DIR, is_save=false || SAVE_ALL, is_show=true, diff --git a/examples/ram_air_kite.jl b/examples/ram_air_kite.jl index 2c9b790b..4a114b5c 100644 --- a/examples/ram_air_kite.jl +++ b/examples/ram_air_kite.jl @@ -99,7 +99,7 @@ if PLOT [body_xfoil, body_nf], ["XFoil", "NeuralFoil"]; angle_range=range(-5, 25, length=31), - v_a=va, + va=va, title="Ram Air Kite: XFoil vs NeuralFoil", is_save=false, use_tex=USE_TEX diff --git a/examples/rectangular_wing.jl b/examples/rectangular_wing.jl index badb3a89..2e45aa99 100644 --- a/examples/rectangular_wing.jl +++ b/examples/rectangular_wing.jl @@ -94,7 +94,7 @@ PLOT && plot_polars( ["LLT", "VSM"]; angle_range, angle_type="angle_of_attack", - v_a=va, + va=va, title="Rectangular Wing Polars", save_path=OUTPUT_DIR, is_save=false || SAVE_ALL, diff --git a/examples/stall_model.jl b/examples/stall_model.jl index 6b6acb3a..f37c6d3e 100644 --- a/examples/stall_model.jl +++ b/examples/stall_model.jl @@ -123,7 +123,7 @@ PLOT && plot_polars( angle_type="angle_of_attack", angle_of_attack=aoa, side_slip=side_slip, - v_a=va, + va=va, title="tutorial_testing_stall_model_n_panels_$(n_panels)_distribution_$(spanwise_distribution)", save_path=OUTPUT_DIR, is_save=false || SAVE_ALL, diff --git a/ext/VortexStepMethodMakieExt.jl b/ext/VortexStepMethodMakieExt.jl index 3cd2569a..ebde9043 100644 --- a/ext/VortexStepMethodMakieExt.jl +++ b/ext/VortexStepMethodMakieExt.jl @@ -607,7 +607,7 @@ Create a 3D Makie plot of wing geometry including panels and filaments. function create_geometry_plot_makie(body_aero::BodyAerodynamics, title, view_elevation, view_azimuth; zoom=0.5) panels = body_aero.panels - va_vec = getfield(body_aero, :_va) + va_vec = getfield(body_aero, :va_vec) # Create figure fig = Figure(size=(1400, 1400)) @@ -856,7 +856,7 @@ 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, + angle_of_attack=0.0, side_slip=0.0, va=10.0, title="polar", data_type=nothing, save_path=nothing, is_save=true, is_show=true, use_tex=false) @@ -873,7 +873,7 @@ Makie implementation of [`plot_polars`](@ref). - `angle_type`: "angle_of_attack" or "side_slip" (default: angle_of_attack) - `angle_of_attack`: AoA [°] (default: 0.0) - `side_slip`: Side slip angle [°] (default: 0.0) -- `v_a`: Wind speed [m/s] (default: 10.0) +- `va`: apparent wind speed [m/s] (default: 10.0) - `title`: Plot title - `data_type`: File extension (default: `nothing`; delegated to `save_plot` backend-aware default) - `save_path`: Path to save (default: nothing) @@ -891,7 +891,7 @@ function VortexStepMethod.plot_polars( angle_type="angle_of_attack", angle_of_attack=0.0, side_slip=0.0, - v_a=10.0, + va=10.0, title="polar", data_type=nothing, save_path=nothing, @@ -915,7 +915,7 @@ function VortexStepMethod.plot_polars( for (i, (solver, body_aero)) in enumerate(zip(solver_list, body_aero_list)) result = VortexStepMethod.generate_polar_data( solver, body_aero, angle_range; - angle_type, angle_of_attack, side_slip, va=v_a + angle_type, angle_of_attack, side_slip, va ) push!(polar_data_list, result.polar_data) push!(cm_data_list, (cmx=result.cmx, cmy=result.cmy, @@ -1116,7 +1116,7 @@ end 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, + angle_of_attack=0.0, side_slip=0.0, va=10.0, title="Combined Analysis", view_elevation=15, view_azimuth=-120, is_show=true, use_tex=false, @@ -1139,7 +1139,7 @@ Makie implementation of [`plot_combined_analysis`](@ref). - `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) +- `va`: apparent wind speed [m/s] (default: 10.0) - `title`: Overall figure title (default: "Combined Analysis") - `view_elevation`: Geometry view elevation in degrees (default: 15) - `view_azimuth`: Geometry view azimuth in degrees (default: -120) @@ -1162,7 +1162,7 @@ function VortexStepMethod.plot_combined_analysis( angle_type="angle_of_attack", angle_of_attack=0.0, side_slip=0.0, - v_a=10.0, + va=10.0, title="Combined Analysis", view_elevation=15, view_azimuth=-120, @@ -1220,7 +1220,7 @@ function VortexStepMethod.plot_combined_analysis( # Use first body_aero for geometry and polar data display first_body = body_aeros[1] panels = first_body.panels - va_vec = getfield(first_body, :_va) + va_vec = getfield(first_body, :va_vec) # Compute spanwise results for each solver results_spanwise_list = copy(results_list) @@ -1228,10 +1228,10 @@ function VortexStepMethod.plot_combined_analysis( α_span = deg2rad(angle_of_attack_for_spanwise_distribution) β_span = deg2rad(side_slip) for (i, (s, ba)) in enumerate(zip(solvers, body_aeros)) - va_vec_old = copy(getfield(ba, :_va)) + va_vec_old = copy(getfield(ba, :va_vec)) omega_old = copy(ba.omega) set_va!(ba, [cos(α_span) * cos(β_span), sin(β_span), - sin(α_span)] * v_a) + sin(α_span)] * va) results_spanwise_list[i] = solve(s, ba, s.sol.gamma_distribution) set_va!(ba, va_vec_old, omega_old) @@ -1406,7 +1406,7 @@ function VortexStepMethod.plot_combined_analysis( zip(solvers, body_aeros, solver_labels)) result = VortexStepMethod.generate_polar_data( s, ba, angle_range; - angle_type, angle_of_attack, side_slip, va=v_a) + angle_type, angle_of_attack, side_slip, va) pd = result.polar_data label_re = "$lbl Re = $(round(Int64, result.rey * 1e-5))e5" diff --git a/mwes/mwe_01.jl b/mwes/mwe_01.jl index c6f0990b..7ac9b5f1 100644 --- a/mwes/mwe_01.jl +++ b/mwes/mwe_01.jl @@ -1,4 +1,4 @@ -# Replace va_dist = norm.(eachrow(solver.sol._va_dist)) with a for loop +# Replace va_dist = norm.(eachrow(solver.sol.va_vec_dist)) with a for loop # Testcase that shows that the new function is equivalent to the old, allocating line of code. using Test diff --git a/mwes/mwe_warntype.jl b/mwes/mwe_warntype.jl index 664a0787..d0762ab2 100644 --- a/mwes/mwe_warntype.jl +++ b/mwes/mwe_warntype.jl @@ -83,4 +83,4 @@ printstyled("\n$sep\n solve_base!\n$sep\n"; color=:cyan) @code_warntype solve_base!(solver, body_aero, nothing) printstyled("\n$sep\n calc_norm_dist!\n$sep\n"; color=:cyan) -@code_warntype calc_norm_dist!(solver.br.va_norm_dist, solver.sol._va_dist) +@code_warntype calc_norm_dist!(solver.br.va_dist, solver.sol.va_vec_dist) diff --git a/src/VortexStepMethod.jl b/src/VortexStepMethod.jl index 4c89927b..f2073e9e 100644 --- a/src/VortexStepMethod.jl +++ b/src/VortexStepMethod.jl @@ -115,7 +115,7 @@ Plot polar data comparing different solvers and configurations. - `angle_type`: `"angle_of_attack"` or `"side_slip"` (default: `"angle_of_attack"`) - `angle_of_attack`: AoA for the polar sweep (default: `0.0`) [°] - `side_slip`: side slip angle (default: `0.0`) [°] -- `v_a`: apparent wind speed magnitude (default: `10.0`) [m/s] +- `va`: apparent wind speed (default: `10.0`) [m/s] - `title`: plot title (default: `"polar"`) - `data_type`: file extension for saving (default: `".png"`) - `save_path`: path to save plots (default: `nothing`) @@ -160,7 +160,7 @@ in sequence. - `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 angle in degrees (default: `0.0`) -- `v_a`: wind speed in m/s (default: `10.0`) +- `va`: apparent wind speed (default: `10.0`) [m/s] - `title`: overall figure title (default: `"Combined Analysis"`) - `view_elevation`: geometry view elevation in degrees (default: `15`) - `view_azimuth`: geometry view azimuth in degrees (default: `-120`) diff --git a/src/body_aerodynamics.jl b/src/body_aerodynamics.jl index 22e97679..f8193ca5 100644 --- a/src/body_aerodynamics.jl +++ b/src/body_aerodynamics.jl @@ -6,7 +6,7 @@ Main structure for calculating aerodynamic properties of bodies. Use the constru # Fields - panels::Vector{<:Panel}: Vector of refined [`Panel`](@ref) structs - wings::Vector{W}: A vector of wings of type `W <: AbstractWing`; a body can have multiple wings -- `va::MVec3` = zeros(MVec3): A vector of the apparent wind speed, see: [`MVec3`](@ref) +- `va_vec::MVec3` = zeros(MVec3): apparent wind vector [m/s], see: [`MVec3`](@ref) - `omega`::MVec3 = zeros(MVec3): A vector of the turn rates around the kite body axes - `reference_point`::MVec3 = zeros(MVec3): The point `omega` turns the body about [m] - `gamma_distribution`=zeros(Float64, P): A vector of the circulation @@ -15,7 +15,8 @@ Main structure for calculating aerodynamic properties of bodies. Use the constru - `alpha_corrected`=zeros(Float64, P): corrected angles of attack per panel - `stall_angle_list`=zeros(Float64, P): stall angle per panel - `alpha_dist::MVector{P, Float64}` = zeros(Float64, P) -- `v_a_dist::MVector{P, Float64}` = zeros(Float64, P) +- `v_rel_dist::MVector{P, Float64}` = zeros(Float64, P): norm of the relative velocity + crossed with the panel spanwise axis, |v_rel × y_airf| [m/s] - `pitch_rate_dist::MVector{P, Float64}` = zeros(Float64, P): rotation rate of each panel about its own spanwise axis, positive nose-up [rad/s]; set by [`set_va!`](@ref) and read when the solver has `flow_curvature` enabled @@ -33,7 +34,7 @@ Main structure for calculating aerodynamic properties of bodies. Use the constru @with_kw mutable struct BodyAerodynamics{P, W<:AbstractWing, T, PN<:Panel{T}} panels::Vector{PN} wings::Vector{W} - _va::MVector{3, T} = zeros(MVector{3, T}) + va_vec::MVector{3, T} = zeros(MVector{3, T}) has_distributed_va::Bool = false omega::MVector{3, T} = zeros(MVector{3, T}) reference_point::MVector{3, T} = zeros(MVector{3, T}) @@ -42,7 +43,7 @@ Main structure for calculating aerodynamic properties of bodies. Use the constru alpha_corrected::MVector{P, T} = zeros(MVector{P, T}) stall_angle_list::MVector{P, T} = zeros(MVector{P, T}) alpha_dist::MVector{P, T} = zeros(MVector{P, T}) - v_a_dist::MVector{P, T} = zeros(MVector{P, T}) + v_rel_dist::MVector{P, T} = zeros(MVector{P, T}) pitch_rate_dist::MVector{P, T} = zeros(MVector{P, T}) work_vectors::NTuple{10, MVector{3, T}} = ntuple(_ -> zeros(MVector{3, T}), 10) AIC::Array{T, 3} = zeros(T, P, P, 3) @@ -67,7 +68,7 @@ aerodynamic properties, returning a fully initialized structure ready for simula # Keyword Arguments - `kite_body_origin=zeros(MVec3)`: Origin point of kite body reference frame in CAD reference frame -- `va=[15.0, 0.0, 0.0]`: Apparent wind vector +- `va_vec=[15.0, 0.0, 0.0]`: Apparent wind vector [m/s] - `omega=zeros(3)`: Turn rate in kite body frame x y and z # Returns @@ -76,13 +77,13 @@ aerodynamic properties, returning a fully initialized structure ready for simula # Example ```julia wing = Wing("wing.yaml"; n_panels=40); refine!(wing) -body_aero = BodyAerodynamics([wing], va=[15.0, 0.0, 0.0], omega=zeros(3)) +body_aero = BodyAerodynamics([wing], va_vec=[15.0, 0.0, 0.0], omega=zeros(3)) ``` """ function BodyAerodynamics( wings::Vector{W}; kite_body_origin=zeros(MVec3), - va=[15.0, 0.0, 0.0], + va_vec=[15.0, 0.0, 0.0], omega=zeros(MVec3) ) where {T, W <: AbstractWing{T}} # Validate all wings are refined @@ -124,7 +125,7 @@ function BodyAerodynamics( end body_aero = BodyAerodynamics{length(panels), W, T, eltype(panels)}(; panels, wings) - reinit!(body_aero; va, omega) + reinit!(body_aero; va_vec, omega) return body_aero end @@ -140,25 +141,22 @@ wing_span_flip(wing) = wing.spanwise_direction) < 0 ? Int8(-1) : Int8(1) function Base.getproperty(obj::BodyAerodynamics, sym::Symbol) - if sym === :va - if getfield(obj, :has_distributed_va) - throw(ArgumentError( - "body_aero.va is undefined after set_va! with distributed inflow. " * - "Use panel.va or solver.sol._va_dist for per-panel inflow data." - )) - end - return getfield(obj, :_va) + if sym === :va_vec && getfield(obj, :has_distributed_va) + throw(ArgumentError( + "body_aero.va_vec is undefined after set_va! with distributed inflow. " * + "Use panel.va_vec or solver.sol.va_vec_dist for per-panel inflow data." + )) end return getfield(obj, sym) end function Base.setproperty!(obj::BodyAerodynamics, sym::Symbol, val) - if sym === :va + if sym === :va_vec set_va!(obj, val) elseif sym === :omega - set_va!(obj, obj._va, val) + set_va!(obj, getfield(obj, :va_vec), val) elseif sym === :reference_point - set_va!(obj, obj._va, obj.omega; reference_point=val) + set_va!(obj, getfield(obj, :va_vec), obj.omega; reference_point=val) else setfield!(obj, sym, val) end @@ -288,7 +286,7 @@ function unrefined_deform!(body_aero::BodyAerodynamics, theta_angles, delta_angl end """ - reinit!(body_aero::BodyAerodynamics; init_aero, va, omega, refine_mesh, recompute_mapping, sort_sections) + reinit!(body_aero::BodyAerodynamics; init_aero, va_vec, omega) Initialize a BodyAerodynamics struct in-place by setting up panels and coefficients. @@ -297,7 +295,7 @@ Initialize a BodyAerodynamics struct in-place by setting up panels and coefficie # Keyword Arguments - `init_aero::Bool`: Whether to initialize the aero data or not -- `va=[15.0, 0.0, 0.0]`: Apparent wind vector +- `va_vec=[15.0, 0.0, 0.0]`: Apparent wind vector [m/s] - `omega=zeros(3)`: Turn rate in kite body frame x y and z # Returns @@ -305,7 +303,7 @@ nothing """ function reinit!(body_aero::BodyAerodynamics{P, W, T}; init_aero=true, - va=[15.0, 0.0, 0.0], + va_vec=[15.0, 0.0, 0.0], omega=zeros(MVector{3, T}) ) where {P, W, T} idx = 1 @@ -353,9 +351,9 @@ function reinit!(body_aero::BodyAerodynamics{P, W, T}; body_aero.c_ref = maximum(panel.chord for panel in body_aero.panels) calculate_stall_angle_list!(body_aero.stall_angle_list, body_aero.panels) body_aero.alpha_dist .= 0.0 - body_aero.v_a_dist .= 0.0 + body_aero.v_rel_dist .= 0.0 body_aero.AIC .= 0.0 - set_va!(body_aero, va, omega) + set_va!(body_aero, va_vec, omega) return nothing end @@ -858,9 +856,9 @@ function calculate_results( alpha_geometric[i] = NaN else inv_va = 1.0 / va - v_tangential = -dot3(panel.x_airf, panel.va) * + v_tangential = -dot3(panel.x_airf, panel.va_vec) * inv_va / x_norm - v_normal = -dot3(panel.z_airf, panel.va) * + v_normal = -dot3(panel.z_airf, panel.va_vec) * inv_va / z_norm alpha_geometric[i] = atan(-v_normal, -v_tangential) end @@ -964,22 +962,22 @@ function calculate_results( "velocity magnitude.")) q_panel = 0.5 * density * va_panel^2 cross3!(dir_lift_prescribed_va, - panel.va, spanwise_direction) + panel.va_vec, spanwise_direction) normalize3!(dir_lift_prescribed_va) - cross3!(temp_vec, dir_lift_prescribed_va, panel.va) + cross3!(temp_vec, dir_lift_prescribed_va, panel.va_vec) inv_va_panel = 1.0 / va_panel @inbounds for k in 1:3 temp_vec[k] *= inv_va_panel end lift_prescribed_va = dot(force, dir_lift_prescribed_va) - drag_prescribed_va = dot(force, panel.va) * inv_va_panel + drag_prescribed_va = dot(force, panel.va_vec) * inv_va_panel side_prescribed_va = dot(force, temp_vec) lift_wing_3D_sum += lift_prescribed_va * dot3(dir_lift_prescribed_va, dir_lift_ref) drag_wing_3D_sum += drag_prescribed_va * - (dot3(panel.va, va_ref_unit) * inv_va_panel) + (dot3(panel.va_vec, va_ref_unit) * inv_va_panel) side_wing_3D_sum += side_prescribed_va * dot3(temp_vec, dir_side_ref) @@ -1072,7 +1070,7 @@ function calculate_results( "aspect_ratio_projected" => aspect_ratio_projected, "Rey" => reynolds_number, "q_ref" => q_ref, - "va_ref" => va_ref_vec, + "va_ref_vec" => va_ref_vec, "center_of_pressure" => center_of_pressure, "panel_cp_locations" => panel_cp_locations ) @@ -1111,13 +1109,13 @@ function set_va!(body_aero::BodyAerodynamics{P, W, T}, va_vec::AbstractVector, va_vec_dist = zeros(T, P, 3) for (i, panel) in enumerate(body_aero.panels) - panel.va .= va_vec .- omega × (panel.control_point .- body_aero.reference_point) - va_vec_dist[i, :] .= panel.va + panel.va_vec .= va_vec .- omega × (panel.control_point .- body_aero.reference_point) + va_vec_dist[i, :] .= panel.va_vec end # Update wake elements frozen_wake!(body_aero, va_vec_dist) - body_aero._va .= va_vec + getfield(body_aero, :va_vec) .= va_vec body_aero.has_distributed_va = false return nothing end @@ -1147,30 +1145,30 @@ function set_va!(body_aero::BodyAerodynamics, va_vec_dist::AbstractMatrix; end for (i, panel) in enumerate(body_aero.panels) - panel.va .= va_vec_dist[i, :] + panel.va_vec .= va_vec_dist[i, :] end # Update wake elements frozen_wake!(body_aero, va_vec_dist) - body_aero._va .= [mean(va_vec_dist[:,i]) for i in 1:3] + getfield(body_aero, :va_vec) .= [mean(va_vec_dist[:,i]) for i in 1:3] body_aero.has_distributed_va = true return nothing end """ - apparent_wind(alpha, beta, wind_speed) + apparent_wind(alpha, beta, va) Apparent wind vector in the body frame [m/s] at angle of attack `alpha` [rad], sideslip -`beta` [rad] and `wind_speed` [m/s]. +`beta` [rad] and apparent wind speed `va` [m/s]. """ -apparent_wind(alpha, beta, wind_speed) = - wind_speed .* [cos(alpha) * cos(beta), sin(beta), sin(alpha) * cos(beta)] +apparent_wind(alpha, beta, va) = + va .* [cos(alpha) * cos(beta), sin(beta), sin(alpha) * cos(beta)] """ set_va!(body_aero::BodyAerodynamics, settings::VSMSettings) Set the uniform inflow of `body_aero` to the [`apparent_wind`](@ref) at the `alpha` and -`beta` [°] and `wind_speed` [m/s] of `settings.condition`, turning the body about +`beta` [°] and apparent wind speed `va` [m/s] of `settings.condition`, turning the body about `body_aero.reference_point` at its `yaw_rate` [°/s] about Z_b. # Example @@ -1183,6 +1181,6 @@ set_va!(body_aero, settings) function set_va!(body_aero::BodyAerodynamics, settings::VSMSettings) condition = settings.condition va_vec = apparent_wind(deg2rad(condition.alpha), deg2rad(condition.beta), - condition.wind_speed) + condition.va) set_va!(body_aero, va_vec, [0.0, 0.0, deg2rad(condition.yaw_rate)]) end diff --git a/src/filament.jl b/src/filament.jl index b4993542..023addec 100644 --- a/src/filament.jl +++ b/src/filament.jl @@ -166,14 +166,14 @@ Represents a semi-infinite vortex filament. # Fields - x1::MVec3=zeros(MVec3): Starting point - direction::MVec3=zeros(MVec3): Direction vector -- `vel_mag`::Float64=zero(Float64): Velocity magnitude +- `va`::Float64=zero(Float64): apparent wind speed [m/s] - `filament_direction`::Int64=0 : Direction indicator (-1 or 1) - initialized::Bool=false """ @with_kw mutable struct SemiInfiniteFilament{T} <: Filament x1::MVector{3, T} = zeros(MVector{3, T}) direction::MVector{3, T} = zeros(MVector{3, T}) - vel_mag::T = zero(T) + va::T = zero(T) filament_direction::Int64 = zero(Int64) initialized::Bool = false end @@ -182,7 +182,7 @@ function reinit!(filament::SemiInfiniteFilament{T}, x1::AbstractVector, direction::AbstractVector, va::Real, filament_direction::Real) where T filament.x1 .= x1 filament.direction .= direction - filament.vel_mag = va + filament.va = va filament.filament_direction = filament_direction filament.initialized = true return nothing diff --git a/src/panel.jl b/src/panel.jl index 6957dd0c..3f0b413a 100644 --- a/src/panel.jl +++ b/src/panel.jl @@ -9,7 +9,7 @@ Represents a panel in a vortex step method simulation. All points and vectors ar - `TE_point_2`::MVec3=zeros(MVec3): Second trailing edge point - `LE_point_2`::MVec3=zeros(MVec3): Second leading edge point - `chord`::Float64=0: Panel chord length -- `va`::MVec3=zeros(MVec3): Panel velocity +- `va_vec`::MVec3=zeros(MVec3): apparent wind vector at the panel [m/s] - `corner_points`::MMatrix{3, 4, Float64}=zeros(MMatrix{3, 4, Float64}: Panel corner points - `aero_model`::AeroModel=INVISCID: Aerodynamic model type [`AeroModel`](@ref) - `aero_center::Vector{Float64}`: Panel aerodynamic center @@ -47,7 +47,7 @@ Represents a panel in a vortex step method simulation. All points and vectors ar TE_point_2::MVector{3, T} = zeros(MVector{3, T}) LE_point_2::MVector{3, T} = zeros(MVector{3, T}) chord::T = zero(T) - va::MVector{3, T} = zeros(MVector{3, T}) + va_vec::MVector{3, T} = zeros(MVector{3, T}) corner_points::MMatrix{3, 4, T, 12} = zeros(MMatrix{3, 4, T, 12}) aero_model::AeroModel = INVISCID cl_coeffs::Vector{Float64} = zeros(Float64, 3) @@ -474,7 +474,7 @@ function calculate_relative_alpha_and_relative_velocity( panel::Panel{T}, induced_velocity::AbstractVector{T} ) where T - flow = panel_inflow(panel_axes(panel), panel.va, panel.va, induced_velocity) + flow = panel_inflow(panel_axes(panel), panel.va_vec, panel.va_vec, induced_velocity) return flow.alpha, flow.v_eff end @@ -484,7 +484,7 @@ end Calculate relative angle of attack and relative velocity of the panel. """ function calculate_relative_alpha_and_velocity(panel::Panel, induced_velocity) - flow = panel_inflow(panel_axes(panel), panel.va, panel.va, induced_velocity) + flow = panel_inflow(panel_axes(panel), panel.va_vec, panel.va_vec, induced_velocity) return flow.alpha, flow.v_eff end @@ -611,7 +611,7 @@ function calculate_filaments_for_plotting(panel::Panel) color = i == 1 ? "magenta" : "green" # bound vs trailing else # For semi-infinite filaments - x2 = x1 + 2 * panel.chord * (panel.va / norm(panel.va)) + x2 = x1 + 2 * panel.chord * (panel.va_vec / norm(panel.va_vec)) color = "orange" if filament.filament_direction == -1 diff --git a/src/settings.jl b/src/settings.jl index ae4b0f7a..6b13a4e2 100644 --- a/src/settings.jl +++ b/src/settings.jl @@ -9,7 +9,7 @@ function parse_enum(::Type{T}, s::String) where T <: Enum end @with_kw mutable struct ConditionSettings - wind_speed::Float64 = 10.0 # wind speed [m/s] + va::Float64 = 10.0 # apparent wind speed [m/s] alpha::Float64 = 5.0 # angle of attack [°] beta::Float64 = 0.0 # sideslip angle [°] yaw_rate::Float64 = 0.0 # yaw rate [°/s] @@ -78,7 +78,7 @@ generated at different transition settings or off different networks. for a dataset generated without a flap sweep (default `nothing`). - `live_offsets`: Angles [deg] off the reference angle a live polar is sampled at (default `-12:3:12`). -- `v_app`: Apparent wind [m/s] the polars' Reynolds number is taken at +- `va`: apparent wind speed [m/s] the polars' Reynolds number is taken at (default `25.0`). - `chord_ref`: Reference (maximum panel) chord [m], which Reynolds is defined against (default `1.0`). @@ -95,7 +95,7 @@ generated at different transition settings or off different networks. alpha_range::Vector{Float64} = [-180.0, 1.0, 180.0] delta_range::Union{Nothing, Vector{Float64}} = nothing live_offsets::Vector{Float64} = collect(-12.0:3.0:12.0) - v_app::Float64 = 25.0 + va::Float64 = 25.0 chord_ref::Float64 = 1.0 table_format::Symbol = :arrow end diff --git a/src/settings_adapters.jl b/src/settings_adapters.jl index 115d44f5..334f84b1 100644 --- a/src/settings_adapters.jl +++ b/src/settings_adapters.jl @@ -78,11 +78,11 @@ delta_range(airfoil::AirfoilSettings) = """ reynolds(set::VSMSettings, wing::WingSettings) -> Float64 -`density * v_app * chord_ref / mu`, the definition the solver uses. The air comes +`density * va * chord_ref / mu`, the definition the solver uses. The air comes from `solver_settings`, and the reference speed and chord from `wing.airfoil`. """ reynolds(set::VSMSettings, wing::WingSettings) = - set.solver_settings.density * wing.airfoil.v_app * wing.airfoil.chord_ref / + set.solver_settings.density * wing.airfoil.va * wing.airfoil.chord_ref / set.solver_settings.mu """ diff --git a/src/solver.jl b/src/solver.jl index 04bcc7f4..d83ea149 100644 --- a/src/solver.jl +++ b/src/solver.jl @@ -39,7 +39,7 @@ Struct for storing the solution of the [`solve!`](@ref) function. Must contain a _x_airf_dist::Matrix{T} = zeros(T, P, 3) _y_airf_dist::Matrix{T} = zeros(T, P, 3) _z_airf_dist::Matrix{T} = zeros(T, P, 3) - _va_dist::Matrix{T} = zeros(T, P, 3) + va_vec_dist::Matrix{T} = zeros(T, P, 3) _chord_dist::Vector{T} = zeros(T, P) ### end of private vectors width_dist::Vector{T} = zeros(T, P) @@ -72,7 +72,7 @@ Struct for storing the solution of the [`solve!`](@ref) function. Must contain a x_airf_unrefined_dist::Vector{MVector{3, T}} = [zeros(MVector{3, T}) for _ in 1:U] y_airf_unrefined_dist::Vector{MVector{3, T}} = [zeros(MVector{3, T}) for _ in 1:U] z_airf_unrefined_dist::Vector{MVector{3, T}} = [zeros(MVector{3, T}) for _ in 1:U] - va_unrefined_dist::Vector{MVector{3, T}} = [zeros(MVector{3, T}) for _ in 1:U] + va_vec_unrefined_dist::Vector{MVector{3, T}} = [zeros(MVector{3, T}) for _ in 1:U] chord_unrefined_dist::MVector{U, T} = zeros(MVector{U, T}) width_unrefined_dist::MVector{U, T} = zeros(MVector{U, T}) unrefined_count_dist::Vector{Int} = zeros(Int, U) @@ -84,12 +84,12 @@ end converged::Bool = false gamma_new::MVector{P, T} = zeros(MVector{P, T}) alpha_dist::MVector{P, T} = zeros(MVector{P, T}) - v_a_dist::MVector{P, T} = zeros(MVector{P, T}) + v_rel_dist::MVector{P, T} = zeros(MVector{P, T}) v_span_dist::MVector{P, T} = zeros(MVector{P, T}) end @with_kw struct BaseResult{P, T} - va_norm_dist::MVector{P, T} = zeros(MVector{P, T}) + va_dist::MVector{P, T} = zeros(MVector{P, T}) va_unit_dist::Matrix{T} = zeros(T, P, 3) end @@ -361,7 +361,7 @@ function calc_forces!(solver::Solver{P, U, T}, body_aero::BodyAerodynamics; alpha_dist = solver.lr.alpha_dist alpha_corrected = solver.sol.alpha_dist alpha_geometric_dist = solver.sol.alpha_geometric_dist - v_rel_dist = solver.lr.v_a_dist + v_rel_dist = solver.lr.v_rel_dist panels = body_aero.panels width_dist = solver.sol.width_dist @@ -386,9 +386,9 @@ function calc_forces!(solver::Solver{P, U, T}, body_aero::BodyAerodynamics; # Geometric AoA using panel-local axes and prescribed # freestream — scalar ops to avoid allocations begin - va1 = solver.sol._va_dist[i,1] - va2 = solver.sol._va_dist[i,2] - va3 = solver.sol._va_dist[i,3] + va1 = solver.sol.va_vec_dist[i,1] + va2 = solver.sol.va_vec_dist[i,2] + va3 = solver.sol.va_vec_dist[i,3] va = sqrt(va1^2 + va2^2 + va3^2) x1 = solver.sol._x_airf_dist[i,1] x2 = solver.sol._x_airf_dist[i,2] @@ -427,8 +427,8 @@ function calc_forces!(solver::Solver{P, U, T}, body_aero::BodyAerodynamics; solver.core_radius_fraction, solver.sol._z_airf_dist, solver.sol._x_airf_dist, - solver.sol._va_dist, - solver.br.va_norm_dist, + solver.sol.va_vec_dist, + solver.br.va_dist, solver.br.va_unit_dist ) else @@ -483,7 +483,7 @@ function calc_forces!(solver::Solver{P, U, T}, body_aero::BodyAerodynamics; # Python parity: normalize with area-weighted reference velocity for distributed inflow. va_ref_vec = _compute_reference_velocity_from_distribution( - solver.sol._va_dist, + solver.sol.va_vec_dist, length(panels), panel_areas ) @@ -503,7 +503,7 @@ function calc_forces!(solver::Solver{P, U, T}, body_aero::BodyAerodynamics; 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 + va_vec_unrefined_dist = solver.sol.va_vec_unrefined_dist chord_unrefined_dist = solver.sol.chord_unrefined_dist width_unrefined_dist = solver.sol.width_unrefined_dist unrefined_count_dist = solver.sol.unrefined_count_dist @@ -519,7 +519,7 @@ function calc_forces!(solver::Solver{P, U, T}, body_aero::BodyAerodynamics; 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 + va_vec_unrefined_dist[i] .= 0.0 end chord_unrefined_dist .= 0.0 width_unrefined_dist .= 0.0 @@ -546,7 +546,7 @@ function calc_forces!(solver::Solver{P, U, T}, body_aero::BodyAerodynamics; 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 + va_vec_unrefined_dist[target_unrefined_idx] .+= panel.va_vec chord_unrefined_dist[target_unrefined_idx] += panel.chord width_unrefined_dist[target_unrefined_idx] += panel.width @@ -567,7 +567,7 @@ function calc_forces!(solver::Solver{P, U, T}, body_aero::BodyAerodynamics; 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 + va_vec_unrefined_dist[target_unrefined_idx] ./= count chord_unrefined_dist[target_unrefined_idx] /= count # width_unrefined_dist is NOT averaged - it is the # sum of panel widths in the unrefined section @@ -638,12 +638,12 @@ function solve(solver::Solver, body_aero::BodyAerodynamics, gamma_distribution=n solver.core_radius_fraction, solver.mu, solver.lr.alpha_dist, - solver.lr.v_a_dist, + solver.lr.v_rel_dist, solver.sol._chord_dist, solver.sol._x_airf_dist, solver.sol._z_airf_dist, - solver.sol._va_dist, - solver.br.va_norm_dist, + solver.sol.va_vec_dist, + solver.br.va_dist, solver.br.va_unit_dist, body_aero.panels, solver.is_only_f_and_gamma_output; @@ -698,7 +698,7 @@ function solve_base!(solver::Solver{P, U, T}, body_aero::BodyAerodynamics, gamma # check arguments check_dimensions(solver, body_aero) - isnothing(body_aero.panels[1].va) && throw(ArgumentError( + isnothing(body_aero.panels[1].va_vec) && throw(ArgumentError( "Inflow conditions are not set, use set_va!(body_aero, va_vec)")) # Initialize variables @@ -710,7 +710,7 @@ function solve_base!(solver::Solver{P, U, T}, body_aero::BodyAerodynamics, gamma 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.va_vec_dist .= 0 solver.sol._chord_dist .= 0 # Fill arrays from panels @@ -719,23 +719,23 @@ function solve_base!(solver::Solver{P, U, T}, body_aero::BodyAerodynamics, gamma solver.sol._x_airf_dist[i, k] = panel.x_airf[k] solver.sol._y_airf_dist[i, k] = panel.y_airf[k] solver.sol._z_airf_dist[i, k] = panel.z_airf[k] - solver.sol._va_dist[i, k] = panel.va[k] + solver.sol.va_vec_dist[i, k] = panel.va_vec[k] end solver.sol._chord_dist[i] = panel.chord end # Calculate unit vectors - calc_norm_dist!(solver.br.va_norm_dist, solver.sol._va_dist) + calc_norm_dist!(solver.br.va_dist, solver.sol.va_vec_dist) @inbounds for i in 1:n_panels - inv_norm = 1.0 / solver.br.va_norm_dist[i] + inv_norm = 1.0 / solver.br.va_dist[i] for k in 1:3 solver.br.va_unit_dist[i, k] = - solver.sol._va_dist[i, k] * inv_norm + solver.sol.va_vec_dist[i, k] * inv_norm end end # Calculate AIC matrices - calculate_AIC_matrices!(body_aero, solver.aerodynamic_model_type, solver.core_radius_fraction, solver.br.va_norm_dist, + calculate_AIC_matrices!(body_aero, solver.aerodynamic_model_type, solver.core_radius_fraction, solver.br.va_dist, solver.br.va_unit_dist) # Initialize gamma distribution @@ -837,7 +837,7 @@ end solver.lr.alpha_dist .= atan.(v_normal_dist, v_tangential_dist) @inbounds for i in 1:n_panels - solver.lr.v_a_dist[i] = smooth_sqrt( + solver.lr.v_rel_dist[i] = smooth_sqrt( relative_velocity_crossz[i,1]^2 + relative_velocity_crossz[i,2]^2 + relative_velocity_crossz[i,3]^2) @@ -850,7 +850,7 @@ end for (i, (panel, alpha)) in enumerate(zip(panels, solver.lr.alpha_dist)) cl_dist[i] = calculate_cl(panel, alpha) end - gamma_out .= 0.5 .* solver.lr.v_a_dist.^2 ./ va_magw_dist .* cl_dist .* chord_dist + gamma_out .= 0.5 .* solver.lr.v_rel_dist.^2 ./ va_magw_dist .* cl_dist .* chord_dist return nothing end @@ -958,7 +958,7 @@ function gamma_loop!( relaxation_factor; log::Bool = true ) where {P, U, T} - va_vec_dist = solver.sol._va_dist + va_vec_dist = solver.sol.va_vec_dist chord_dist = solver.sol._chord_dist x_airf_dist = solver.sol._x_airf_dist y_airf_dist = solver.sol._y_airf_dist @@ -966,9 +966,9 @@ function gamma_loop!( solver.lr.converged = false n_panels = length(body_aero.panels) solver.lr.alpha_dist .= body_aero.alpha_dist - solver.lr.v_a_dist .= body_aero.v_a_dist + solver.lr.v_rel_dist .= body_aero.v_rel_dist - va_magw_dist = solver.cache[1][solver.lr.v_a_dist] + va_magw_dist = solver.cache[1][solver.lr.v_rel_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_vec_dist] @@ -1277,7 +1277,7 @@ function make_dual_shadow(solver::Solver{P, U, Float64}, ::Type{TD}) where {P, U, W, TD} wings_d = [_wing_with_eltype(wing, TD) for wing in body_aero.wings] body_aero_d = BodyAerodynamics(wings_d) - set_va!(body_aero_d, MVector{3, TD}(body_aero._va), MVector{3, TD}(body_aero.omega); + set_va!(body_aero_d, MVector{3, TD}(getfield(body_aero, :va_vec)), MVector{3, TD}(body_aero.omega); reference_point=body_aero.reference_point) solver_d = Solver(P, U, TD; solver_type = solver.solver_type, @@ -1307,7 +1307,7 @@ end """ linearize(solver, body_aero, y; theta_idxs=1:4, delta_idxs=nothing, - va_idxs=nothing, omega_idxs=nothing, aero_coeffs=false, + va_vec_idxs=nothing, omega_idxs=nothing, aero_coeffs=false, backend=AutoForwardDiff(), kwargs...) Jacobian of aerodynamic outputs w.r.t. control and kinematic inputs at `y`. Each `*_idxs` @@ -1326,7 +1326,7 @@ warning) if any internal solve missed the solver's tolerances. function linearize(solver::Solver{<:Any, U}, body_aero::BodyAerodynamics, y::Vector{T}; theta_idxs=1:4, delta_idxs=nothing, - va_idxs=nothing, + va_vec_idxs=nothing, omega_idxs=nothing, aero_coeffs=false, backend = AutoForwardDiff(), @@ -1350,7 +1350,7 @@ function linearize(solver::Solver{<:Any, U}, body_aero::BodyAerodynamics, y::Vec solver_c = solver else shadow = shadow_ref[] - if shadow === nothing || eltype(shadow[1]._va) !== TI + if shadow === nothing || eltype(shadow[1].va_vec) !== TI shadow_ref[] = make_dual_shadow(solver, body_aero, TI) end body_aero_c, solver_c = shadow_ref[] @@ -1364,7 +1364,8 @@ function linearize(solver::Solver{<:Any, U}, body_aero::BodyAerodynamics, y::Vec reinit!(body_aero_c; init_aero=false) end - va_vec = isnothing(va_idxs) ? MVector{3, TI}(body_aero_c._va) : y_in[va_idxs] + va_vec = isnothing(va_vec_idxs) ? MVector{3, TI}(getfield(body_aero_c, :va_vec)) : + y_in[va_vec_idxs] omega = isnothing(omega_idxs) ? MVector{3, TI}(body_aero_c.omega) : y_in[omega_idxs] set_va!(body_aero_c, va_vec, omega) diff --git a/src/stability.jl b/src/stability.jl index 9ca803cf..88a7fa55 100644 --- a/src/stability.jl +++ b/src/stability.jl @@ -1,8 +1,8 @@ """ - stability_derivatives(solver, body_aero, alpha, beta, wind_speed; kwargs...) + stability_derivatives(solver, body_aero, alpha, beta, va; kwargs...) Aerodynamic coefficients `[CFx, CFy, CFz, CMx, CMy, CMz]` of `body_aero` at angle of attack -`alpha` [rad], sideslip `beta` [rad] and `wind_speed` [m/s], and their derivatives with +`alpha` [rad], sideslip `beta` [rad] and apparent wind speed `va` [m/s], and their derivatives with respect to `alpha` and `beta` [1/rad], at the rotation rate `body_aero.omega` and with moments about `solver.reference_point`. `kwargs` go to [`linearize`](@ref), which leaves `body_aero` at this inflow. @@ -10,40 +10,40 @@ moments about `solver.reference_point`. `kwargs` go to [`linearize`](@ref), whic Returns `(coeffs, dalpha, dbeta, converged)`. """ function stability_derivatives(solver::Solver, body_aero::BodyAerodynamics, alpha, beta, - wind_speed; kwargs...) - va_vec = apparent_wind(alpha, beta, wind_speed) + va; kwargs...) + va_vec = apparent_wind(alpha, beta, va) jac, results, converged = linearize(solver, body_aero, va_vec; - theta_idxs=nothing, va_idxs=1:3, aero_coeffs=true, kwargs...) + theta_idxs=nothing, va_vec_idxs=1:3, aero_coeffs=true, kwargs...) dva_dalpha = ForwardDiff.derivative( - angle -> apparent_wind(angle, beta, wind_speed), alpha) + angle -> apparent_wind(angle, beta, va), alpha) dva_dbeta = ForwardDiff.derivative( - angle -> apparent_wind(alpha, angle, wind_speed), beta) + angle -> apparent_wind(alpha, angle, va), beta) coeff_jac = jac[1:6, :] return (coeffs=results[1:6], dalpha=coeff_jac * dva_dalpha, dbeta=coeff_jac * dva_dbeta, converged) end """ - trim_angle(solver, body_aero, beta, wind_speed; alpha_range=deg2rad.(-5:2:15), + trim_angle(solver, body_aero, beta, va; alpha_range=deg2rad.(-5:2:15), alpha_tol=1e-5, backend=AutoForwardDiff()) Angles of attack [rad] at which `CMy` of `body_aero` about `solver.reference_point` changes sign between neighbouring entries of `alpha_range`, bisected to `alpha_tol` [rad], at -sideslip `beta` [rad] and `wind_speed` [m/s]. Returns one `(alpha, dCMy_dalpha)` per trim, +sideslip `beta` [rad] and apparent wind speed `va` [m/s]. Returns one `(alpha, dCMy_dalpha)` per trim, the slope [1/rad] from [`stability_derivatives`](@ref) with `backend`; a trim is statically stable where `dCMy_dalpha < 0`. Throws a [`SolveFailure`](@ref) if a solve misses the solver's tolerances. """ -function trim_angle(solver::Solver, body_aero::BodyAerodynamics, beta, wind_speed; +function trim_angle(solver::Solver, body_aero::BodyAerodynamics, beta, va; alpha_range=deg2rad.(-5:2:15), alpha_tol=1e-5, backend=AutoForwardDiff()) - is_nose_down = alpha -> nose_down(solver, body_aero, alpha, beta, wind_speed) + is_nose_down = alpha -> nose_down(solver, body_aero, alpha, beta, va) nose_down_range = is_nose_down.(alpha_range) trims = @NamedTuple{alpha::Float64, dCMy_dalpha::Float64}[] for i in 1:length(alpha_range)-1 nose_down_range[i] == nose_down_range[i+1] && continue alpha = bisect_sign_change(is_nose_down, alpha_range[i], alpha_range[i+1], alpha_tol) - derivatives = stability_derivatives(solver, body_aero, alpha, beta, wind_speed; + derivatives = stability_derivatives(solver, body_aero, alpha, beta, va; backend, throw_on_fail=true) push!(trims, (alpha=alpha, dCMy_dalpha=derivatives.dalpha[5])) end @@ -51,26 +51,26 @@ function trim_angle(solver::Solver, body_aero::BodyAerodynamics, beta, wind_spee end """ - coeffs_at_angles(solver, body_aero, alpha, beta, wind_speed) + coeffs_at_angles(solver, body_aero, alpha, beta, va) Aerodynamic coefficients `[CFx, CFy, CFz, CMx, CMy, CMz]` of `body_aero` solved at angle of -attack `alpha` [rad], sideslip `beta` [rad] and `wind_speed` [m/s], at the rotation rate +attack `alpha` [rad], sideslip `beta` [rad] and apparent wind speed `va` [m/s], at the rotation rate `body_aero.omega`. Throws a [`SolveFailure`](@ref) if the solve misses the solver's tolerances. """ -function coeffs_at_angles(solver, body_aero, alpha, beta, wind_speed) - set_va!(body_aero, apparent_wind(alpha, beta, wind_speed), body_aero.omega) +function coeffs_at_angles(solver, body_aero, alpha, beta, va) + set_va!(body_aero, apparent_wind(alpha, beta, va), body_aero.omega) sol = solve!(solver, body_aero; throw_on_fail=true) return [sol.force_coeffs; sol.moment_coeffs] end """ - nose_down(solver, body_aero, alpha, beta, wind_speed) + nose_down(solver, body_aero, alpha, beta, va) Whether `CMy` from [`coeffs_at_angles`](@ref) is negative. """ -nose_down(solver, body_aero, alpha, beta, wind_speed) = - coeffs_at_angles(solver, body_aero, alpha, beta, wind_speed)[5] < 0 +nose_down(solver, body_aero, alpha, beta, va) = + coeffs_at_angles(solver, body_aero, alpha, beta, va)[5] < 0 """ bisect_sign_change(predicate, low, high, tol) diff --git a/test/bench.jl b/test/bench.jl index 197e3e33..95a0d45a 100644 --- a/test/bench.jl +++ b/test/bench.jl @@ -114,7 +114,7 @@ using LinearAlgebra # Fill arrays with data for (i, panel) in enumerate(body_aero.panels) - va_vec_dist[i, :] .= panel.va + va_vec_dist[i, :] .= panel.va_vec chord_dist[i] = panel.chord x_airf_dist[i, :] .= panel.x_airf y_airf_dist[i, :] .= panel.y_airf @@ -145,7 +145,7 @@ using LinearAlgebra solver = Solver(wing.n_panels, wing.n_unrefined_sections; aerodynamic_model_type=model ) - solver.sol._va_dist .= va_vec_dist + solver.sol.va_vec_dist .= va_vec_dist solver.sol._chord_dist .= chord_dist solver.sol._x_airf_dist .= x_airf_dist solver.sol._y_airf_dist .= y_airf_dist @@ -184,9 +184,9 @@ using LinearAlgebra x_airf_dist[i, :] .= panel.x_airf y_airf_dist[i, :] .= panel.y_airf z_airf_dist[i, :] .= panel.z_airf - va_vec_dist[i, :] .= panel.va - va_dist[i] = norm(panel.va) - va_unit_dist[i, :] .= va_dist[i] > 0.0 ? panel.va ./ va_dist[i] : [1.0, 0.0, 0.0] + va_vec_dist[i, :] .= panel.va_vec + va_dist[i] = norm(panel.va_vec) + va_unit_dist[i, :] .= va_dist[i] > 0.0 ? panel.va_vec ./ va_dist[i] : [1.0, 0.0, 0.0] v_rel_dist[i] = va_dist[i] end results = @MVector zeros(3) diff --git a/test/body_aerodynamics/complete_settings.yaml b/test/body_aerodynamics/complete_settings.yaml index 214f7c30..dc70d402 100644 --- a/test/body_aerodynamics/complete_settings.yaml +++ b/test/body_aerodynamics/complete_settings.yaml @@ -14,4 +14,4 @@ solver_settings: condition: alpha: 10.0 beta: 5.0 - wind_speed: 15.0 + va: 15.0 diff --git a/test/body_aerodynamics/test_body_aerodynamics.jl b/test/body_aerodynamics/test_body_aerodynamics.jl index 7024b410..a691e3ee 100644 --- a/test/body_aerodynamics/test_body_aerodynamics.jl +++ b/test/body_aerodynamics/test_body_aerodynamics.jl @@ -433,7 +433,7 @@ end @testset "set_va! with VSMSettings applies the yaw rate about body z" begin settings_file = create_temp_wing_settings("body_aerodynamics", "test_wing.yaml"; - alpha=10.0, beta=5.0, wind_speed=15.0, + alpha=10.0, beta=5.0, va=15.0, yaw_rate=30.0) try settings = VSMSettings(settings_file) @@ -443,21 +443,21 @@ end set_va!(body_aero, settings) - α, β, wind_speed = deg2rad(10.0), deg2rad(5.0), 15.0 - expected_va_vec = wind_speed .* [cos(α)*cos(β), sin(β), sin(α)*cos(β)] + α, β, va = deg2rad(10.0), deg2rad(5.0), 15.0 + expected_va_vec = va .* [cos(α)*cos(β), sin(β), sin(α)*cos(β)] omega = [0.0, 0.0, deg2rad(30.0)] for p in body_aero.panels - @test p.va ≈ expected_va_vec .- omega × p.control_point atol=1e-10 + @test p.va_vec ≈ expected_va_vec .- omega × p.control_point atol=1e-10 end - @test body_aero._va ≈ expected_va_vec atol=1e-10 + @test body_aero.va_vec ≈ expected_va_vec atol=1e-10 @test body_aero.omega ≈ omega finally isfile(settings_file) && rm(settings_file; force=true) end end -@testset "set_va! with distributed inflow blocks body_aero.va access" begin +@testset "set_va! with distributed inflow blocks body_aero.va_vec access" begin body_aero = BodyAerodynamics([inviscid_wing([0.0, 1.0, 2.0])]) va_vec_dist = [ @@ -468,7 +468,7 @@ end @test body_aero.has_distributed_va try - body_aero.va + body_aero.va_vec @test false catch err @test err isa ArgumentError @@ -477,7 +477,7 @@ end set_va!(body_aero, [11.0, 0.0, 0.0]) @test !body_aero.has_distributed_va - @test body_aero.va ≈ [11.0, 0.0, 0.0] + @test body_aero.va_vec ≈ [11.0, 0.0, 0.0] end @testset "set_va! with omega on multi-wing body" begin @@ -490,19 +490,20 @@ end for panel in body_aero.panels expected_va_vec = va_vec .+ (-omega × panel.control_point) - @test panel.va ≈ expected_va_vec atol=1e-12 + @test panel.va_vec ≈ expected_va_vec atol=1e-12 end @test body_aero.omega ≈ omega @test !body_aero.has_distributed_va - @test body_aero.va ≈ va_vec + @test body_aero.va_vec ≈ va_vec + @test_throws FieldError body_aero.va new_omega = [0.0, 0.0, 2.0] - @test body_aero._va ≈ va_vec + @test body_aero.va_vec ≈ va_vec body_aero.omega = new_omega for panel in body_aero.panels expected_va_vec = va_vec .+ (-new_omega × panel.control_point) - @test panel.va ≈ expected_va_vec atol=1e-12 + @test panel.va_vec ≈ expected_va_vec atol=1e-12 end @test body_aero.omega ≈ new_omega end @@ -516,7 +517,7 @@ Test that every panel sees `va_vec` plus the inflow of a body turning at `omega` function test_rigid_body_inflow(body_aero, va_vec, omega, reference_point) for panel in body_aero.panels expected_va_vec = va_vec .- omega × (panel.control_point .- reference_point) - @test panel.va ≈ expected_va_vec atol=1e-12 + @test panel.va_vec ≈ expected_va_vec atol=1e-12 end end @@ -534,7 +535,7 @@ end body_aero.omega = 2 .* omega test_rigid_body_inflow(body_aero, va_vec, 2 .* omega, reference_point) - reinit!(body_aero; va=va_vec, omega) + reinit!(body_aero; va_vec=va_vec, omega) test_rigid_body_inflow(body_aero, va_vec, omega, reference_point) body_aero.reference_point = zeros(3) @@ -547,7 +548,7 @@ end The `BodyAerodynamics` built from `wings` in a 10 m/s inflow and its `solve!` solution. """ function solve_wings(wings) - body_aero = BodyAerodynamics(wings; va=[10.0, 0.0, 1.0]) + body_aero = BodyAerodynamics(wings; va_vec=[10.0, 0.0, 1.0]) solver = Solver(sum(wing -> wing.n_panels, wings), sum(wing -> wing.n_unrefined_sections, wings)) return body_aero, solve!(solver, body_aero) @@ -573,10 +574,10 @@ function linearize_body(body_aero; kwargs...) n_sections = sum(wing -> wing.n_unrefined_sections, body_aero.wings) solver = Solver(sum(wing -> wing.n_panels, body_aero.wings), n_sections; use_gamma_prev=false, rtol=1e-10) - y0 = [zeros(2n_sections); body_aero.va; zeros(3)] + y0 = [zeros(2n_sections); body_aero.va_vec; zeros(3)] return VortexStepMethod.linearize(solver, body_aero, y0; theta_idxs=1:n_sections, delta_idxs=n_sections+1:2n_sections, - va_idxs=2n_sections+1:2n_sections+3, omega_idxs=2n_sections+4:2n_sections+6, + va_vec_idxs=2n_sections+1:2n_sections+3, omega_idxs=2n_sections+4:2n_sections+6, kwargs...) end diff --git a/test/body_aerodynamics/test_results.jl b/test/body_aerodynamics/test_results.jl index 98fa96ad..f6dff19a 100644 --- a/test/body_aerodynamics/test_results.jl +++ b/test/body_aerodynamics/test_results.jl @@ -31,7 +31,7 @@ end fd_step = 1e-3 VortexStepMethod.unrefined_deform!(ram_wing, theta, delta; smooth=false) - body_aero = BodyAerodynamics([ram_wing]; va=va_vec, omega) + body_aero = BodyAerodynamics([ram_wing]; va_vec, omega) solver = Solver(ram_wing.n_panels, ram_wing.n_unrefined_sections; aerodynamic_model_type=VSM, is_with_artificial_damping=false, @@ -43,7 +43,7 @@ end base_inputs = [theta; va_vec; omega; delta] jac, lin_res, lin_converged = VortexStepMethod.linearize( solver, body_aero, base_inputs; - theta_idxs=1:4, va_idxs=5:7, omega_idxs=8:10, delta_idxs=11:14, + theta_idxs=1:4, va_vec_idxs=5:7, omega_idxs=8:10, delta_idxs=11:14, moment_frac=0.1, backend=AutoFiniteDiff(absstep=fd_step, relstep=fd_step), ) @@ -61,7 +61,7 @@ end VortexStepMethod.unrefined_deform!( ram_wing, perturbed_theta, perturbed_delta; smooth=false) reinit!(body_aero; init_aero=false, - va=perturbed_va_vec, omega=perturbed_omega) + va_vec=perturbed_va_vec, omega=perturbed_omega) VortexStepMethod.solve!(solver, body_aero; log=false) return [solver.sol.force; solver.sol.moment; solver.sol.moment_unrefined_dist] diff --git a/test/filament/test_semi_infinite_filament.jl b/test/filament/test_semi_infinite_filament.jl index 826ae0f9..b68314ed 100644 --- a/test/filament/test_semi_infinite_filament.jl +++ b/test/filament/test_semi_infinite_filament.jl @@ -52,13 +52,13 @@ end filament.direction, control_point, gamma, - filament.vel_mag, + filament.va, work_vectors ) analytical = analytical_solution( control_point, gamma, filament.x1, filament.direction, - filament.filament_direction, filament.vel_mag + filament.filament_direction, filament.va ) @test isapprox(induced_velocity, analytical, rtol=1e-6) @@ -80,7 +80,7 @@ end filament.direction, start_point, gamma, - filament.vel_mag, + filament.va, work_vectors ) @test all(isnan.(induced_velocity)) @@ -92,7 +92,7 @@ end filament.direction, point, gamma, - filament.vel_mag, + filament.va, work_vectors ) @test all(isapprox.(induced_velocity, zeros(3), atol=1e-5)) @@ -106,9 +106,9 @@ end v2 = zeros(3) v4 = zeros(3) - velocity_3D_trailing_vortex_semiinfinite!(v1, filament, filament.direction, control_point, 1.0, filament.vel_mag, work_vectors) - velocity_3D_trailing_vortex_semiinfinite!(v2, filament, filament.direction, control_point, 2.0, filament.vel_mag, work_vectors) - velocity_3D_trailing_vortex_semiinfinite!(v4, filament, filament.direction, control_point, 4.0, filament.vel_mag, work_vectors) + velocity_3D_trailing_vortex_semiinfinite!(v1, filament, filament.direction, control_point, 1.0, filament.va, work_vectors) + velocity_3D_trailing_vortex_semiinfinite!(v2, filament, filament.direction, control_point, 2.0, filament.va, work_vectors) + velocity_3D_trailing_vortex_semiinfinite!(v4, filament, filament.direction, control_point, 4.0, filament.va, work_vectors) @test isapprox(v4, 2 * v2) @test isapprox(v4, 4 * v1) @@ -125,7 +125,7 @@ end filament.direction, [0.0, 1.0, 0.0], gamma, - filament.vel_mag, + filament.va, work_vectors ) velocity_3D_trailing_vortex_semiinfinite!( @@ -134,7 +134,7 @@ end filament.direction, [0.0, -1.0, 0.0], gamma, - filament.vel_mag, + filament.va, work_vectors ) @@ -151,7 +151,7 @@ end v = zeros(3) velocity_3D_trailing_vortex_semiinfinite!( v, filament, direction, p, gamma, - filament.vel_mag, work_vectors) + filament.va, work_vectors) r_radial = [0.0, p[2], p[3]] @test isapprox(dot(v, direction), 0.0; atol=1e-10) @@ -162,7 +162,7 @@ end @testset "Constant azimuthal direction inside core" begin filament = create_test_filament2() - va = filament.vel_mag + va = filament.va d_inside = 1e-4 v1 = zeros(3); v2 = zeros(3) diff --git a/test/panel/test_panel.jl b/test/panel/test_panel.jl index f6381c18..cd744346 100644 --- a/test/panel/test_panel.jl +++ b/test/panel/test_panel.jl @@ -99,7 +99,7 @@ end section1 = Section([0.0, 0.0, 0.0], [1.0, 0.0, 0.0], INVISCID) section2 = Section([0.0, 10.0, 0.0], [1.0, 10.0, 0.0], INVISCID) panel = create_panel(section1, section2) - panel.va = [10.0, 0.0, 0.0] + panel.va_vec = [10.0, 0.0, 0.0] filaments = VortexStepMethod.calculate_filaments_for_plotting(panel) @test filaments isa Vector{Tuple{Vector{Float64}, Vector{Float64}, String}} @@ -112,14 +112,14 @@ end panel = create_panel(section1, section2) # Test relative velocity calculations - panel.va = [10.0, 0.0, 0.0] + panel.va_vec = [10.0, 0.0, 0.0] induced_velocity = [1.0, 1.0, 1.0] alpha, rel_vel = calculate_relative_alpha_and_relative_velocity(panel, induced_velocity) # Verify calculations norm_airf = panel.z_airf tan_airf = panel.x_airf - relative_velocity = panel.va .+ induced_velocity + relative_velocity = panel.va_vec .+ induced_velocity vn = dot(norm_airf, relative_velocity) vtan = dot(tan_airf, relative_velocity) expected_alpha = atan(vn / vtan) diff --git a/test/plotting/test_plotting.jl b/test/plotting/test_plotting.jl index 38354e8c..e6620d66 100644 --- a/test/plotting/test_plotting.jl +++ b/test/plotting/test_plotting.jl @@ -110,7 +110,7 @@ end ["VSM", "LLT"], angle_range=angle_range, angle_type="angle_of_attack", - v_a=va, + va=va, title="Rectangular Wing Polars", data_type=".png", save_path=save_dir, @@ -127,7 +127,7 @@ end ["VSM", "LLT"], angle_range=angle_range, angle_type="angle_of_attack", - v_a=va, + va=va, title="Polars CL vs CD", is_save=false, is_show=false, @@ -141,7 +141,7 @@ end angle_range=angle_range, angle_type="angle_of_attack", angle_of_attack=30.0, - v_a=va, + va=va, title="Combined Analysis", is_save=false, is_show=false, @@ -155,7 +155,7 @@ end angle_range=angle_range, angle_type="angle_of_attack", angle_of_attack=30.0, - v_a=va, + va=va, title="Combined CL vs CD", is_save=false, is_show=false, diff --git a/test/settings/basic_llt.yaml b/test/settings/basic_llt.yaml index 78b79edd..ee189373 100644 --- a/test/settings/basic_llt.yaml +++ b/test/settings/basic_llt.yaml @@ -6,4 +6,4 @@ solver_settings: condition: alpha: 5.0 beta: 0.0 - wind_speed: 20.0 + va: 20.0 diff --git a/test/settings/basic_vsm.yaml b/test/settings/basic_vsm.yaml index 63dee5dc..ff2f3b9a 100644 --- a/test/settings/basic_vsm.yaml +++ b/test/settings/basic_vsm.yaml @@ -6,4 +6,4 @@ solver_settings: condition: alpha: 10.0 beta: 5.0 - wind_speed: 15.0 + va: 15.0 diff --git a/test/settings/test_settings.jl b/test/settings/test_settings.jl index 38484c6d..52bde77d 100644 --- a/test/settings/test_settings.jl +++ b/test/settings/test_settings.jl @@ -40,7 +40,7 @@ end n_crit: 4.0 alpha_range: [-15, 3, 90] delta_range: [-40, 10, 40] - v_app: 25.0 + va: 25.0 chord_ref: 6.0 table_format: csv solver_settings: diff --git a/test/solver/solver_settings.yaml b/test/solver/solver_settings.yaml index 142c0c1f..6e36659e 100644 --- a/test/solver/solver_settings.yaml +++ b/test/solver/solver_settings.yaml @@ -14,4 +14,4 @@ solver_settings: condition: alpha: 5.0 beta: 0.0 - wind_speed: 10.0 + va: 10.0 diff --git a/test/solver/test_flow_curvature.jl b/test/solver/test_flow_curvature.jl index 2639e344..dc6bfb87 100644 --- a/test/solver/test_flow_curvature.jl +++ b/test/solver/test_flow_curvature.jl @@ -150,7 +150,7 @@ end for i in 1:n @test solver_on.sol.cm_dist[i] - base[i] ≈ flow_curvature_cm(rates[i], solver_on.sol._chord_dist[i], - solver_on.lr.v_a_dist[i]) + solver_on.lr.v_rel_dist[i]) end # the two half-wings must be driven in opposite senses @test sign(solver_on.sol.cm_dist[1] - base[1]) == diff --git a/test/solver/test_forwarddiff.jl b/test/solver/test_forwarddiff.jl index de4d6c8f..8169dec4 100644 --- a/test/solver/test_forwarddiff.jl +++ b/test/solver/test_forwarddiff.jl @@ -33,13 +33,13 @@ relative_error(jac, reference) = maximum(abs.(jac .- reference)) / maximum(abs, jac_fwd, _, fwd_converged = VortexStepMethod.linearize( solver, pivot_body, y_op; - theta_idxs=nothing, va_idxs=1:3, omega_idxs=4:6, + theta_idxs=nothing, va_vec_idxs=1:3, omega_idxs=4:6, aero_coeffs=true, backend=AutoForwardDiff()) @test fwd_converged jac_fd, _, fd_converged = VortexStepMethod.linearize( solver, pivot_body, y_op; - theta_idxs=nothing, va_idxs=1:3, omega_idxs=4:6, + theta_idxs=nothing, va_vec_idxs=1:3, omega_idxs=4:6, aero_coeffs=true, backend=AutoFiniteDiff(absstep=1e-5, relstep=1e-5)) @test fd_converged @@ -52,7 +52,7 @@ relative_error(jac, reference) = maximum(abs.(jac .- reference)) / maximum(abs, solver_nl = Solver(wing.n_panels, wing.n_unrefined_sections; solver_type=NONLIN) @test_throws ErrorException VortexStepMethod.linearize( solver_nl, body_aero, y0; - theta_idxs=nothing, va_idxs=1:3, omega_idxs=4:6, + theta_idxs=nothing, va_vec_idxs=1:3, omega_idxs=4:6, aero_coeffs=true, backend=AutoForwardDiff()) end @@ -86,13 +86,13 @@ relative_error(jac, reference) = maximum(abs.(jac .- reference)) / maximum(abs, jac_fwd, _, conv_fwd = VortexStepMethod.linearize( ram_solver, ram_body, y_op; - theta_idxs=1:4, va_idxs=5:7, omega_idxs=8:10, + theta_idxs=1:4, va_vec_idxs=5:7, omega_idxs=8:10, aero_coeffs=true, backend=AutoForwardDiff()) @test conv_fwd jac_fd, _, conv_fd = VortexStepMethod.linearize( ram_solver, ram_body, y_op; - theta_idxs=1:4, va_idxs=5:7, omega_idxs=8:10, + theta_idxs=1:4, va_vec_idxs=5:7, omega_idxs=8:10, aero_coeffs=true, backend=nothing) @test conv_fd diff --git a/test/solver/test_solver.jl b/test/solver/test_solver.jl index 2dceee9d..ec6a5f74 100644 --- a/test/solver/test_solver.jl +++ b/test/solver/test_solver.jl @@ -10,7 +10,7 @@ end @testset "Solver Constructor Tests" begin @testset "Solver Constructor with VSMSettings" begin # Use module-specific test data files - settings_file = create_temp_wing_settings("solver", "solver_test_wing.yaml"; alpha=5.0, beta=0.0, wind_speed=10.0) + settings_file = create_temp_wing_settings("solver", "solver_test_wing.yaml"; alpha=5.0, beta=0.0, va=10.0) try # Test Solver constructor with VSMSettings @@ -72,7 +72,7 @@ end @testset "NONLIN solve! re-runs across calls" begin settings_file = create_temp_wing_settings( "solver", "solver_test_wing.yaml"; - alpha=5.0, beta=0.0, wind_speed=10.0, + alpha=5.0, beta=0.0, va=10.0, ) try settings = VSMSettings(settings_file) @@ -106,7 +106,7 @@ end @testset "NONLIN converges past stall, where LOOP already did" begin settings_file = create_temp_wing_settings( "solver", "solver_test_wing.yaml"; - alpha=5.0, beta=0.0, wind_speed=10.0, + alpha=5.0, beta=0.0, va=10.0, ) try settings = VSMSettings(settings_file) @@ -151,7 +151,7 @@ end @testset "LOOP converges on the residual, not on the relaxed step" begin settings_file = create_temp_wing_settings( "solver", "solver_test_wing.yaml"; - alpha=5.0, beta=0.0, wind_speed=10.0, + alpha=5.0, beta=0.0, va=10.0, ) try settings = VSMSettings(settings_file) @@ -180,7 +180,7 @@ calc_forces_allocs(solver, body_aero) = @testset "calc_forces! is zero-alloc" begin settings_file = create_temp_wing_settings( "solver", "solver_test_wing.yaml"; - alpha=5.0, beta=0.0, wind_speed=10.0, + alpha=5.0, beta=0.0, va=10.0, ) try settings = VSMSettings(settings_file) diff --git a/test/solver/test_stability.jl b/test/solver/test_stability.jl index 7145322d..55f82ec7 100644 --- a/test/solver/test_stability.jl +++ b/test/solver/test_stability.jl @@ -33,44 +33,44 @@ end @testset "stability_derivatives match central differences of solve!" begin body_aero, solver = trimmable_wing(0.05; reference_point=[0.25, 0.5, 0.1], use_gamma_prev=false) - alpha, beta, wind_speed, step = deg2rad(4.0), deg2rad(3.0), 20.0, 1e-4 + alpha, beta, va, step = deg2rad(4.0), deg2rad(3.0), 20.0, 1e-4 - derivatives = stability_derivatives(solver, body_aero, alpha, beta, wind_speed) + derivatives = stability_derivatives(solver, body_aero, alpha, beta, va) @test derivatives.converged @test derivatives.coeffs ≈ - coeffs_at_angles(solver, body_aero, alpha, beta, wind_speed) + coeffs_at_angles(solver, body_aero, alpha, beta, va) central_difference(coeffs_plus, coeffs_minus) = (coeffs_plus - coeffs_minus) / 2step dalpha = central_difference( - coeffs_at_angles(solver, body_aero, alpha + step, beta, wind_speed), - coeffs_at_angles(solver, body_aero, alpha - step, beta, wind_speed)) + coeffs_at_angles(solver, body_aero, alpha + step, beta, va), + coeffs_at_angles(solver, body_aero, alpha - step, beta, va)) dbeta = central_difference( - coeffs_at_angles(solver, body_aero, alpha, beta + step, wind_speed), - coeffs_at_angles(solver, body_aero, alpha, beta - step, wind_speed)) + coeffs_at_angles(solver, body_aero, alpha, beta + step, va), + coeffs_at_angles(solver, body_aero, alpha, beta - step, va)) @test !iszero(dbeta) @test derivatives.dalpha ≈ dalpha rtol = 1e-4 atol = 1e-6 @test derivatives.dbeta ≈ dbeta rtol = 1e-4 atol = 1e-6 end @testset "trim_angle finds where CMy changes sign" begin - beta, wind_speed = 0.0, 20.0 + beta, va = 0.0, 20.0 @testset "moments about the leading edge: stable trim" begin body_aero, solver = trimmable_wing(0.05) - trims = trim_angle(solver, body_aero, beta, wind_speed) + trims = trim_angle(solver, body_aero, beta, va) @test length(trims) == 1 trim = only(trims) - trim_coeffs = coeffs_at_angles(solver, body_aero, trim.alpha, beta, wind_speed) + trim_coeffs = coeffs_at_angles(solver, body_aero, trim.alpha, beta, va) @test abs(trim_coeffs[5]) < 1e-5 @test trim.dCMy_dalpha < 0 - derivatives = stability_derivatives(solver, body_aero, trim.alpha, beta, wind_speed) + derivatives = stability_derivatives(solver, body_aero, trim.alpha, beta, va) @test trim.dCMy_dalpha ≈ derivatives.dalpha[5] end @testset "moments about the trailing edge: unstable trim" begin body_aero, solver = trimmable_wing(-0.05; reference_point=[1.0, 0.0, 0.0]) - trim = only(trim_angle(solver, body_aero, beta, wind_speed)) - trim_coeffs = coeffs_at_angles(solver, body_aero, trim.alpha, beta, wind_speed) + trim = only(trim_angle(solver, body_aero, beta, va)) + trim_coeffs = coeffs_at_angles(solver, body_aero, trim.alpha, beta, va) @test abs(trim_coeffs[5]) < 1e-5 @test trim.dCMy_dalpha > 0 end @@ -78,20 +78,20 @@ end @testset "a NONLIN solver with backend=nothing finds the same trim" begin loop_body, loop_solver = trimmable_wing(0.05) body_aero, solver = trimmable_wing(0.05; solver_type=NONLIN) - trim_loop = only(trim_angle(loop_solver, loop_body, beta, wind_speed)) - trim = only(trim_angle(solver, body_aero, beta, wind_speed; backend=nothing)) + trim_loop = only(trim_angle(loop_solver, loop_body, beta, va)) + trim = only(trim_angle(solver, body_aero, beta, va; backend=nothing)) @test trim.alpha ≈ trim_loop.alpha atol = 1e-4 @test trim.dCMy_dalpha ≈ trim_loop.dCMy_dalpha rtol = 1e-4 end @testset "a solve that misses the tolerances throws" begin body_aero, solver = trimmable_wing(0.05; max_iterations=2) - @test_throws SolveFailure trim_angle(solver, body_aero, beta, wind_speed) + @test_throws SolveFailure trim_angle(solver, body_aero, beta, va) end @testset "no sign change in alpha_range: no trim" begin body_aero, solver = trimmable_wing(0.05) - @test isempty(trim_angle(solver, body_aero, beta, wind_speed; + @test isempty(trim_angle(solver, body_aero, beta, va; alpha_range=deg2rad.(4:2:12))) end end diff --git a/test/solver/test_unrefined_dist.jl b/test/solver/test_unrefined_dist.jl index 6c676cc0..92c58030 100644 --- a/test/solver/test_unrefined_dist.jl +++ b/test/solver/test_unrefined_dist.jl @@ -9,7 +9,7 @@ using Test 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) + settings_file = create_temp_wing_settings("solver", "solver_test_wing.yaml"; alpha=5.0, beta=0.0, va=10.0) try # Modify settings to use specific panel configuration @@ -86,7 +86,7 @@ using Test # sum(coeff_panel * width_panel * chord_panel) for all panels in section settings_file = create_temp_wing_settings( "solver", "solver_test_wing.yaml"; - alpha=5.0, beta=0.0, wind_speed=10.0) + alpha=5.0, beta=0.0, va=10.0) try settings = VSMSettings(settings_file) @@ -159,7 +159,7 @@ using Test ] 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) + settings_file = create_temp_wing_settings("solver", "solver_test_wing.yaml"; alpha=5.0, beta=0.0, va=10.0) try settings = VSMSettings(settings_file) diff --git a/test/solver/test_viscous_drag_correction.jl b/test/solver/test_viscous_drag_correction.jl index 1358f00c..628a87c4 100644 --- a/test/solver/test_viscous_drag_correction.jl +++ b/test/solver/test_viscous_drag_correction.jl @@ -47,7 +47,7 @@ end delta_force = force_dist_at(solver_on, va_vec) .- force_dist_at(solver_off, va_vec) for (i, panel) in enumerate(body_aero.panels) - v_normal = solver_on.lr.v_a_dist[i] + v_normal = solver_on.lr.v_rel_dist[i] v_span = solver_on.lr.v_span_dist[i] cos_beta = v_normal / hypot(v_normal, v_span) f0 = 0.062 * (density * v_normal * panel.chord / mu)^(-1 / 7) @@ -82,7 +82,7 @@ end @testset "linearize reports the corrected forces" begin y = [va_vec_sideslip; zeros(3)] results_for(solver) = VortexStepMethod.linearize(solver, body_aero, y; - theta_idxs=nothing, va_idxs=1:3, omega_idxs=4:6)[2] + theta_idxs=nothing, va_vec_idxs=1:3, omega_idxs=4:6)[2] results_on, results_off = results_for(solver_on), results_for(solver_off) @test results_on[1:3] ≈ vec(sum(force_dist_at(solver_on, va_vec_sideslip); dims=2)) @test !(results_on[1:3] ≈ results_off[1:3]) diff --git a/test/test_data_utils.jl b/test/test_data_utils.jl index 268c3bb5..401c6801 100644 --- a/test/test_data_utils.jl +++ b/test/test_data_utils.jl @@ -117,7 +117,7 @@ Useful for tests that need to modify settings while using standard wing geometri # Example ```julia -settings_file = create_temp_wing_settings("body_aerodynamics", "test_wing.yaml"; alpha=15.0, wind_speed=25.0) +settings_file = create_temp_wing_settings("body_aerodynamics", "test_wing.yaml"; alpha=15.0, va=25.0) # Use settings_file... rm(settings_file) ``` @@ -134,7 +134,7 @@ function create_temp_wing_settings(module_name, wing_file; type_initial_gamma_distribution="ZEROS", alpha=10.0, beta=5.0, - wind_speed=15.0, + va=15.0, yaw_rate=0.0, ) wing_file_path = isabspath(wing_file) ? wing_file : test_data_path(module_name, wing_file) @@ -158,7 +158,7 @@ function create_temp_wing_settings(module_name, wing_file; "condition" => Dict( "alpha" => alpha, "beta" => beta, - "wind_speed" => wind_speed, + "va" => va, "yaw_rate" => yaw_rate, ), ) diff --git a/test/thesis_oriol_cayon.jl b/test/thesis_oriol_cayon.jl index 759be642..4859464a 100644 --- a/test/thesis_oriol_cayon.jl +++ b/test/thesis_oriol_cayon.jl @@ -74,10 +74,10 @@ function output_results(Fmag, aero_coeffs, ringvec, Uinf, controlpoints, Atot) SFtot += SideF[i] * norm(ringvec[i]["r0"]) end - v_a = norm(Uinf) - CL = Ltot / (0.5 * v_a^2 * Atot * rho) - CD = Dtot / (0.5 * v_a^2 * Atot * rho) - CS = SFtot / (0.5 * v_a^2 * Atot * rho) + va = norm(Uinf) + CL = Ltot / (0.5 * va^2 * Atot * rho) + CD = Dtot / (0.5 * va^2 * Atot * rho) + CS = SFtot / (0.5 * va^2 * Atot * rho) return F_rel, F_gl, Ltot, Dtot, CL, CD, CS end diff --git a/test/verification/test_verification.jl b/test/verification/test_verification.jl index d90bdce8..8dcff408 100644 --- a/test/verification/test_verification.jl +++ b/test/verification/test_verification.jl @@ -49,19 +49,19 @@ function wing_from_coordinates(coordinates, aero_model, aero_data=nothing; end """ - lift_drag_polar(wing, model, alphas; wind_speed, relaxation_factor) + lift_drag_polar(wing, model, alphas; va, relaxation_factor) Wing `CL` and `CD` at each angle of attack in `alphas` [deg], solved with the settings of the Python verification cases. """ -function lift_drag_polar(wing, model, alphas; wind_speed, relaxation_factor) +function lift_drag_polar(wing, model, alphas; va, relaxation_factor) body_aero = BodyAerodynamics([wing]) solver = Solver(wing.n_panels, wing.n_unrefined_sections; aerodynamic_model_type=model, relaxation_factor, core_radius_fraction=1e-20) CL = zeros(length(alphas)) CD = zeros(length(alphas)) for (i, alpha) in enumerate(alphas) - set_va!(body_aero, wind_speed .* [cosd(alpha), 0.0, sind(alpha)]) + set_va!(body_aero, va .* [cosd(alpha), 0.0, sind(alpha)]) results = solve(solver, body_aero) CL[i] = results["cl"] CD[i] = results["cd"] @@ -90,9 +90,9 @@ max_error(actual, expected) = maximum(abs.(actual .- expected)) alphas = [3.0, 9.0] coordinates = generate_coordinates_el_wing(max_chord, span, 40, "cos") wing = wing_from_coordinates(coordinates, INVISCID) - CL_llt, CD_llt = lift_drag_polar(wing, LLT, alphas; wind_speed=20.0, + CL_llt, CD_llt = lift_drag_polar(wing, LLT, alphas; va=20.0, relaxation_factor=0.05) - CL_vsm, CD_vsm = lift_drag_polar(wing, VSM, alphas; wind_speed=20.0, + CL_vsm, CD_vsm = lift_drag_polar(wing, VSM, alphas; va=20.0, relaxation_factor=0.05) CL_theory = 2π .* deg2rad.(alphas) ./ (1 + 2 / aspect_ratio) CD_theory = CL_theory .^ 2 ./ (π * aspect_ratio) @@ -111,9 +111,9 @@ max_error(actual, expected) = maximum(abs.(actual .- expected)) "lin") polar = polar_vectors(read_columns("clarky_polar.csv")...) wing = wing_from_coordinates(coordinates, POLAR_VECTORS, polar) - CL_llt, CD_llt = lift_drag_polar(wing, LLT, alphas; wind_speed=20.0, + CL_llt, CD_llt = lift_drag_polar(wing, LLT, alphas; va=20.0, relaxation_factor=0.03) - CL_vsm, CD_vsm = lift_drag_polar(wing, VSM, alphas; wind_speed=20.0, + CL_vsm, CD_vsm = lift_drag_polar(wing, VSM, alphas; va=20.0, relaxation_factor=0.03) alpha_rans, CL_rans, CD_rans, _ = read_columns("curved_wing_rans.csv") @@ -130,9 +130,9 @@ max_error(actual, expected) = maximum(abs.(actual .- expected)) zeros(n_sections), zeros(n_sections), n_sections, "lin") polar = polar_vectors(read_columns("naca4415_cfd_polar.csv")...) wing = wing_from_coordinates(coordinates, POLAR_VECTORS, polar) - CL_llt, CD_llt = lift_drag_polar(wing, LLT, alphas; wind_speed=20.0, + CL_llt, CD_llt = lift_drag_polar(wing, LLT, alphas; va=20.0, relaxation_factor=0.03) - CL_vsm, CD_vsm = lift_drag_polar(wing, VSM, alphas; wind_speed=20.0, + CL_vsm, CD_vsm = lift_drag_polar(wing, VSM, alphas; va=20.0, relaxation_factor=0.03) alpha_cfd, CL_cfd = read_columns("rectangular_wing_ar12_cfd.csv") @@ -172,7 +172,7 @@ max_error(actual, expected) = maximum(abs.(actual .- expected)) alphas = [3.0, 6.0, 9.0] wing = wing_from_coordinates(coordinates, POLY, lei_poly_coeffs(0.1, 0.095); n_panels=36, spanwise_distribution=SPLIT_PROVIDED) - CL_vsm, CD_vsm = lift_drag_polar(wing, VSM, alphas; wind_speed=22.0, + CL_vsm, CD_vsm = lift_drag_polar(wing, VSM, alphas; va=22.0, relaxation_factor=0.03) alpha_cl, CL_rans = read_columns("v3_kite_rans_cl.csv") alpha_cd, CD_rans = read_columns("v3_kite_rans_cd.csv") @@ -185,7 +185,7 @@ max_error(actual, expected) = maximum(abs.(actual .- expected)) @testset "three horseshoe vortices match Biot-Savart" begin work_vectors = ntuple(_ -> zeros(3), 10) flow_direction = [1.0, 0.0, 0.0] - wind_speed = 1.0 + va = 1.0 trailing_length = 100.0 evaluation_point = zeros(3) horseshoes = ( @@ -205,21 +205,21 @@ max_error(actual, expected) = maximum(abs.(actual .- expected)) right_velocity = zeros(3) left_leg = SemiInfiniteFilament{Float64}() right_leg = SemiInfiniteFilament{Float64}() - reinit!(left_leg, left, flow_direction, wind_speed, 1) - reinit!(right_leg, right, flow_direction, wind_speed, -1) + reinit!(left_leg, left, flow_direction, va, 1) + reinit!(right_leg, right, flow_direction, va, -1) velocity_3D_trailing_vortex_semiinfinite!(left_velocity, left_leg, - flow_direction, evaluation_point, gamma, wind_speed, work_vectors) + flow_direction, evaluation_point, gamma, va, work_vectors) velocity_3D_trailing_vortex_semiinfinite!(right_velocity, right_leg, - flow_direction, evaluation_point, gamma, wind_speed, work_vectors) + flow_direction, evaluation_point, gamma, va, work_vectors) @test bound_velocity + left_velocity + right_velocity ≈ velocity atol=1e-4 wake_offset = trailing_length * flow_direction velocity_3D_trailing_vortex!(left_velocity, bound_filament(left, left + wake_offset), evaluation_point, gamma, - wind_speed, work_vectors) + va, work_vectors) velocity_3D_trailing_vortex!(right_velocity, bound_filament(right + wake_offset, right), evaluation_point, gamma, - wind_speed, work_vectors) + va, work_vectors) @test bound_velocity + left_velocity + right_velocity ≈ velocity atol=1e-4 end end diff --git a/test/yaml_geometry/test_yaml_wing_deformation.jl b/test/yaml_geometry/test_yaml_wing_deformation.jl index 73ecaa64..0a6d3cbc 100644 --- a/test/yaml_geometry/test_yaml_wing_deformation.jl +++ b/test/yaml_geometry/test_yaml_wing_deformation.jl @@ -141,7 +141,7 @@ using Test # Multiple reinit calls should work without errors for _ in 1:3 VortexStepMethod.reinit!(body_aero; - va=zeros(3), + va_vec=zeros(3), omega=zeros(3), init_aero=true, From 46c88a5fd155c842481044720f20640d6c1e6bc4 Mon Sep 17 00:00:00 2001 From: 1-Bort-1 <323661610+1-Bort-1@users.noreply.github.com> Date: Mon, 21 Sep 2026 14:25:53 +0200 Subject: [PATCH 2/4] Wrap the renamed lines at 92 columns and log the BREAKING rename Co-Authored-By: Claude Opus 5 --- CHANGELOG.md | 15 ++++++++++++++- src/body_aerodynamics.jl | 7 ++++--- src/solver.jl | 8 ++++---- src/stability.jl | 16 ++++++++-------- test/bench.jl | 3 ++- test/filament/test_semi_infinite_filament.jl | 9 ++++++--- test/solver/test_solver.jl | 3 ++- test/solver/test_unrefined_dist.jl | 6 ++++-- test/test_data_utils.jl | 3 ++- 9 files changed, 46 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31558fd1..14d79173 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ - `stability_derivatives` gives the force and moment coefficients and their derivatives with respect to angle of attack and sideslip, and `trim_angle` the angles of attack at which `CMy` changes sign, with the slope that says whether each trim is stable. -- `apparent_wind(alpha, beta, wind_speed)` gives the body-frame inflow vector at an angle +- `apparent_wind(alpha, beta, va)` gives the body-frame inflow vector at an angle of attack and sideslip, as `set_va!(body_aero, settings)` sets it. - `Solver(settings)` and `Solver(n_panels, n_unrefined_sections)` build a solver without a `BodyAerodynamics`; keyword arguments override the settings. @@ -30,6 +30,19 @@ - BREAKING: `ObjAdapter.center_to_com!`, `calculate_inertia_tensor` and `calc_inertia_y_rotation` are removed. Mesh mass properties are computed by SymbolicAWEModels, which reads the mesh with `read_faces`. +- BREAKING: the apparent wind is `va` for the speed [m/s], `va_vec` for the 3-vector and + `va_dist` / `va_vec_dist` per panel, and the old names error: + - `body_aero.va` becomes `body_aero.va_vec`, and `va=` becomes `va_vec=` in + `BodyAerodynamics(...)` and `reinit!`. + - `Panel.va` becomes `Panel.va_vec`, and `SemiInfiniteFilament.vel_mag` becomes `va`. + - On `VSMSolution`, `_va_dist` becomes `va_vec_dist` and `va_unrefined_dist` becomes + `va_vec_unrefined_dist`. + - `v_a_dist` on `BodyAerodynamics` and `solver.lr` becomes `v_rel_dist`, and + `solver.br.va_norm_dist` becomes `va_dist`. + - The `linearize` keyword `va_idxs` becomes `va_vec_idxs`, the `calculate_results` key + `"va_ref"` becomes `"va_ref_vec"`, and the `plot_polars` / `plot_combined_analysis` + keyword `v_a` becomes `va`. + - The settings keys `condition.wind_speed` and `airfoil.v_app` become `va`. - Requires Julia 1.12 or 1.13; 1.10 and 1.11 keep resolving v5.1.1. - The Makie `plot!` methods for a `Panel` or a `BodyAerodynamics` return a `Vector{Makie.AbstractPlot}` instead of a `Vector{Any}`; for a `BodyAerodynamics` diff --git a/src/body_aerodynamics.jl b/src/body_aerodynamics.jl index f8193ca5..ee513b15 100644 --- a/src/body_aerodynamics.jl +++ b/src/body_aerodynamics.jl @@ -1109,7 +1109,8 @@ function set_va!(body_aero::BodyAerodynamics{P, W, T}, va_vec::AbstractVector, va_vec_dist = zeros(T, P, 3) for (i, panel) in enumerate(body_aero.panels) - panel.va_vec .= va_vec .- omega × (panel.control_point .- body_aero.reference_point) + panel.va_vec .= va_vec .- + omega × (panel.control_point .- body_aero.reference_point) va_vec_dist[i, :] .= panel.va_vec end @@ -1168,8 +1169,8 @@ apparent_wind(alpha, beta, va) = set_va!(body_aero::BodyAerodynamics, settings::VSMSettings) Set the uniform inflow of `body_aero` to the [`apparent_wind`](@ref) at the `alpha` and -`beta` [°] and apparent wind speed `va` [m/s] of `settings.condition`, turning the body about -`body_aero.reference_point` at its `yaw_rate` [°/s] about Z_b. +`beta` [°] and apparent wind speed `va` [m/s] of `settings.condition`, turning the body +about `body_aero.reference_point` at its `yaw_rate` [°/s] about Z_b. # Example ```julia diff --git a/src/solver.jl b/src/solver.jl index d83ea149..de5d90cb 100644 --- a/src/solver.jl +++ b/src/solver.jl @@ -735,8 +735,8 @@ function solve_base!(solver::Solver{P, U, T}, body_aero::BodyAerodynamics, gamma end # Calculate AIC matrices - calculate_AIC_matrices!(body_aero, solver.aerodynamic_model_type, solver.core_radius_fraction, solver.br.va_dist, - solver.br.va_unit_dist) + calculate_AIC_matrices!(body_aero, solver.aerodynamic_model_type, + solver.core_radius_fraction, solver.br.va_dist, solver.br.va_unit_dist) # Initialize gamma distribution gamma_initial = solver.cache_base[1][solver.sol._chord_dist] @@ -1277,8 +1277,8 @@ function make_dual_shadow(solver::Solver{P, U, Float64}, ::Type{TD}) where {P, U, W, TD} wings_d = [_wing_with_eltype(wing, TD) for wing in body_aero.wings] body_aero_d = BodyAerodynamics(wings_d) - set_va!(body_aero_d, MVector{3, TD}(getfield(body_aero, :va_vec)), MVector{3, TD}(body_aero.omega); - reference_point=body_aero.reference_point) + set_va!(body_aero_d, MVector{3, TD}(getfield(body_aero, :va_vec)), + MVector{3, TD}(body_aero.omega); reference_point=body_aero.reference_point) solver_d = Solver(P, U, TD; solver_type = solver.solver_type, aerodynamic_model_type = solver.aerodynamic_model_type, diff --git a/src/stability.jl b/src/stability.jl index 88a7fa55..9a04b305 100644 --- a/src/stability.jl +++ b/src/stability.jl @@ -2,9 +2,9 @@ stability_derivatives(solver, body_aero, alpha, beta, va; kwargs...) Aerodynamic coefficients `[CFx, CFy, CFz, CMx, CMy, CMz]` of `body_aero` at angle of attack -`alpha` [rad], sideslip `beta` [rad] and apparent wind speed `va` [m/s], and their derivatives with -respect to `alpha` and `beta` [1/rad], at the rotation rate `body_aero.omega` and with -moments about `solver.reference_point`. `kwargs` go to [`linearize`](@ref), which leaves +`alpha` [rad], sideslip `beta` [rad] and apparent wind speed `va` [m/s], and their +derivatives with respect to `alpha` and `beta` [1/rad], at the rotation rate +`body_aero.omega` and with moments about `solver.reference_point`. `kwargs` go to [`linearize`](@ref), which leaves `body_aero` at this inflow. Returns `(coeffs, dalpha, dbeta, converged)`. @@ -29,9 +29,9 @@ end Angles of attack [rad] at which `CMy` of `body_aero` about `solver.reference_point` changes sign between neighbouring entries of `alpha_range`, bisected to `alpha_tol` [rad], at -sideslip `beta` [rad] and apparent wind speed `va` [m/s]. Returns one `(alpha, dCMy_dalpha)` per trim, -the slope [1/rad] from [`stability_derivatives`](@ref) with `backend`; a trim is statically -stable where `dCMy_dalpha < 0`. Throws a [`SolveFailure`](@ref) if a solve misses the +sideslip `beta` [rad] and apparent wind speed `va` [m/s]. Returns one +`(alpha, dCMy_dalpha)` per trim, the slope [1/rad] from [`stability_derivatives`](@ref) +with `backend`; a trim is statically stable where `dCMy_dalpha < 0`. Throws a [`SolveFailure`](@ref) if a solve misses the solver's tolerances. """ function trim_angle(solver::Solver, body_aero::BodyAerodynamics, beta, va; @@ -54,8 +54,8 @@ end coeffs_at_angles(solver, body_aero, alpha, beta, va) Aerodynamic coefficients `[CFx, CFy, CFz, CMx, CMy, CMz]` of `body_aero` solved at angle of -attack `alpha` [rad], sideslip `beta` [rad] and apparent wind speed `va` [m/s], at the rotation rate -`body_aero.omega`. Throws a [`SolveFailure`](@ref) if the solve misses the solver's +attack `alpha` [rad], sideslip `beta` [rad] and apparent wind speed `va` [m/s], at the +rotation rate `body_aero.omega`. Throws a [`SolveFailure`](@ref) if the solve misses the solver's tolerances. """ function coeffs_at_angles(solver, body_aero, alpha, beta, va) diff --git a/test/bench.jl b/test/bench.jl index 95a0d45a..93347449 100644 --- a/test/bench.jl +++ b/test/bench.jl @@ -186,7 +186,8 @@ using LinearAlgebra z_airf_dist[i, :] .= panel.z_airf va_vec_dist[i, :] .= panel.va_vec va_dist[i] = norm(panel.va_vec) - va_unit_dist[i, :] .= va_dist[i] > 0.0 ? panel.va_vec ./ va_dist[i] : [1.0, 0.0, 0.0] + va_unit_dist[i, :] .= + va_dist[i] > 0.0 ? panel.va_vec ./ va_dist[i] : [1.0, 0.0, 0.0] v_rel_dist[i] = va_dist[i] end results = @MVector zeros(3) diff --git a/test/filament/test_semi_infinite_filament.jl b/test/filament/test_semi_infinite_filament.jl index b68314ed..11014cae 100644 --- a/test/filament/test_semi_infinite_filament.jl +++ b/test/filament/test_semi_infinite_filament.jl @@ -106,9 +106,12 @@ end v2 = zeros(3) v4 = zeros(3) - velocity_3D_trailing_vortex_semiinfinite!(v1, filament, filament.direction, control_point, 1.0, filament.va, work_vectors) - velocity_3D_trailing_vortex_semiinfinite!(v2, filament, filament.direction, control_point, 2.0, filament.va, work_vectors) - velocity_3D_trailing_vortex_semiinfinite!(v4, filament, filament.direction, control_point, 4.0, filament.va, work_vectors) + velocity_3D_trailing_vortex_semiinfinite!(v1, filament, filament.direction, + control_point, 1.0, filament.va, work_vectors) + velocity_3D_trailing_vortex_semiinfinite!(v2, filament, filament.direction, + control_point, 2.0, filament.va, work_vectors) + velocity_3D_trailing_vortex_semiinfinite!(v4, filament, filament.direction, + control_point, 4.0, filament.va, work_vectors) @test isapprox(v4, 2 * v2) @test isapprox(v4, 4 * v1) diff --git a/test/solver/test_solver.jl b/test/solver/test_solver.jl index ec6a5f74..98874ff6 100644 --- a/test/solver/test_solver.jl +++ b/test/solver/test_solver.jl @@ -10,7 +10,8 @@ end @testset "Solver Constructor Tests" begin @testset "Solver Constructor with VSMSettings" begin # Use module-specific test data files - settings_file = create_temp_wing_settings("solver", "solver_test_wing.yaml"; alpha=5.0, beta=0.0, va=10.0) + settings_file = create_temp_wing_settings("solver", "solver_test_wing.yaml"; + alpha=5.0, beta=0.0, va=10.0) try # Test Solver constructor with VSMSettings diff --git a/test/solver/test_unrefined_dist.jl b/test/solver/test_unrefined_dist.jl index 92c58030..9bca8a5c 100644 --- a/test/solver/test_unrefined_dist.jl +++ b/test/solver/test_unrefined_dist.jl @@ -9,7 +9,8 @@ using Test 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, va=10.0) + settings_file = create_temp_wing_settings("solver", "solver_test_wing.yaml"; + alpha=5.0, beta=0.0, va=10.0) try # Modify settings to use specific panel configuration @@ -159,7 +160,8 @@ using Test ] 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, va=10.0) + settings_file = create_temp_wing_settings("solver", "solver_test_wing.yaml"; + alpha=5.0, beta=0.0, va=10.0) try settings = VSMSettings(settings_file) diff --git a/test/test_data_utils.jl b/test/test_data_utils.jl index 401c6801..00cdf7f6 100644 --- a/test/test_data_utils.jl +++ b/test/test_data_utils.jl @@ -117,7 +117,8 @@ Useful for tests that need to modify settings while using standard wing geometri # Example ```julia -settings_file = create_temp_wing_settings("body_aerodynamics", "test_wing.yaml"; alpha=15.0, va=25.0) +settings_file = create_temp_wing_settings("body_aerodynamics", "test_wing.yaml"; + alpha=15.0, va=25.0) # Use settings_file... rm(settings_file) ``` From ae38bd2578d4f3236aa61fa85ec2def51520cd29 Mon Sep 17 00:00:00 2001 From: 1-Bort-1 <323661610+1-Bort-1@users.noreply.github.com> Date: Mon, 21 Sep 2026 14:26:43 +0200 Subject: [PATCH 3/4] Wrap the stability docstrings and align the renamed LoopResult field Co-Authored-By: Claude Opus 5 --- src/solver.jl | 4 ++-- src/stability.jl | 12 ++++++------ test/body_aerodynamics/test_body_aerodynamics.jl | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/solver.jl b/src/solver.jl index de5d90cb..8076e1ed 100644 --- a/src/solver.jl +++ b/src/solver.jl @@ -84,7 +84,7 @@ end converged::Bool = false gamma_new::MVector{P, T} = zeros(MVector{P, T}) alpha_dist::MVector{P, T} = zeros(MVector{P, T}) - v_rel_dist::MVector{P, T} = zeros(MVector{P, T}) + v_rel_dist::MVector{P, T} = zeros(MVector{P, T}) v_span_dist::MVector{P, T} = zeros(MVector{P, T}) end @@ -966,7 +966,7 @@ function gamma_loop!( solver.lr.converged = false n_panels = length(body_aero.panels) solver.lr.alpha_dist .= body_aero.alpha_dist - solver.lr.v_rel_dist .= body_aero.v_rel_dist + solver.lr.v_rel_dist .= body_aero.v_rel_dist va_magw_dist = solver.cache[1][solver.lr.v_rel_dist] gamma = solver.cache[2][solver.lr.gamma_new] diff --git a/src/stability.jl b/src/stability.jl index 9a04b305..2ba74529 100644 --- a/src/stability.jl +++ b/src/stability.jl @@ -4,8 +4,8 @@ Aerodynamic coefficients `[CFx, CFy, CFz, CMx, CMy, CMz]` of `body_aero` at angle of attack `alpha` [rad], sideslip `beta` [rad] and apparent wind speed `va` [m/s], and their derivatives with respect to `alpha` and `beta` [1/rad], at the rotation rate -`body_aero.omega` and with moments about `solver.reference_point`. `kwargs` go to [`linearize`](@ref), which leaves -`body_aero` at this inflow. +`body_aero.omega` and with moments about `solver.reference_point`. `kwargs` go to +[`linearize`](@ref), which leaves `body_aero` at this inflow. Returns `(coeffs, dalpha, dbeta, converged)`. """ @@ -31,8 +31,8 @@ Angles of attack [rad] at which `CMy` of `body_aero` about `solver.reference_poi sign between neighbouring entries of `alpha_range`, bisected to `alpha_tol` [rad], at sideslip `beta` [rad] and apparent wind speed `va` [m/s]. Returns one `(alpha, dCMy_dalpha)` per trim, the slope [1/rad] from [`stability_derivatives`](@ref) -with `backend`; a trim is statically stable where `dCMy_dalpha < 0`. Throws a [`SolveFailure`](@ref) if a solve misses the -solver's tolerances. +with `backend`; a trim is statically stable where `dCMy_dalpha < 0`. Throws a +[`SolveFailure`](@ref) if a solve misses the solver's tolerances. """ function trim_angle(solver::Solver, body_aero::BodyAerodynamics, beta, va; alpha_range=deg2rad.(-5:2:15), alpha_tol=1e-5, backend=AutoForwardDiff()) @@ -55,8 +55,8 @@ end Aerodynamic coefficients `[CFx, CFy, CFz, CMx, CMy, CMz]` of `body_aero` solved at angle of attack `alpha` [rad], sideslip `beta` [rad] and apparent wind speed `va` [m/s], at the -rotation rate `body_aero.omega`. Throws a [`SolveFailure`](@ref) if the solve misses the solver's -tolerances. +rotation rate `body_aero.omega`. Throws a [`SolveFailure`](@ref) if the solve misses the +solver's tolerances. """ function coeffs_at_angles(solver, body_aero, alpha, beta, va) set_va!(body_aero, apparent_wind(alpha, beta, va), body_aero.omega) diff --git a/test/body_aerodynamics/test_body_aerodynamics.jl b/test/body_aerodynamics/test_body_aerodynamics.jl index a691e3ee..ec43443f 100644 --- a/test/body_aerodynamics/test_body_aerodynamics.jl +++ b/test/body_aerodynamics/test_body_aerodynamics.jl @@ -535,7 +535,7 @@ end body_aero.omega = 2 .* omega test_rigid_body_inflow(body_aero, va_vec, 2 .* omega, reference_point) - reinit!(body_aero; va_vec=va_vec, omega) + reinit!(body_aero; va_vec, omega) test_rigid_body_inflow(body_aero, va_vec, omega, reference_point) body_aero.reference_point = zeros(3) From c2f1fa3d6c6ae6f2231a3355fdeb4c3e76b29509 Mon Sep 17 00:00:00 2001 From: 1-Bort-1 <323661610+1-Bort-1@users.noreply.github.com> Date: Mon, 21 Sep 2026 14:37:31 +0200 Subject: [PATCH 4/4] Read the shadow's va_vec by getfield and give the removed-name check its own testset Also realign the inline comments after the va: and va_vec_idxs renames. Co-Authored-By: Claude Opus 5 --- data/TUDELFT_V3_KITE/vsm_settings.yaml | 2 +- data/pyramid_model/vsm_settings.yaml | 2 +- docs/src/settings.md | 4 ++-- examples/linearize_check.jl | 8 ++++---- src/solver.jl | 2 +- test/body_aerodynamics/test_body_aerodynamics.jl | 8 +++++++- 6 files changed, 16 insertions(+), 10 deletions(-) diff --git a/data/TUDELFT_V3_KITE/vsm_settings.yaml b/data/TUDELFT_V3_KITE/vsm_settings.yaml index 5a94cf62..d3712c73 100644 --- a/data/TUDELFT_V3_KITE/vsm_settings.yaml +++ b/data/TUDELFT_V3_KITE/vsm_settings.yaml @@ -34,7 +34,7 @@ # Define the flight state for the aerodynamic analysis condition: - va: 2.82 # [m/s] apparent wind speed + va: 2.82 # [m/s] apparent wind speed alpha: 7.4 # [°] Angle of attack (pitch angle relative to flow) beta: 0.0 # [°] Sideslip angle (yaw angle relative to flow) yaw_rate: 0.0 # [°/s] Yaw rate (for dynamic analysis, 0 for static) diff --git a/data/pyramid_model/vsm_settings.yaml b/data/pyramid_model/vsm_settings.yaml index 7e21494a..85984735 100644 --- a/data/pyramid_model/vsm_settings.yaml +++ b/data/pyramid_model/vsm_settings.yaml @@ -34,7 +34,7 @@ # Define the flight state for the aerodynamic analysis condition: - va: 10.0 # [m/s] apparent wind speed + va: 10.0 # [m/s] apparent wind speed alpha: 5.0 # [°] Angle of attack (pitch angle relative to flow) beta: 0.0 # [°] Sideslip angle (yaw angle relative to flow) yaw_rate: 0.0 # [°/s] Yaw rate (for dynamic analysis, 0 for static) diff --git a/docs/src/settings.md b/docs/src/settings.md index 3c6d0573..7d914f46 100644 --- a/docs/src/settings.md +++ b/docs/src/settings.md @@ -29,7 +29,7 @@ values shown are those defaults, and the docstrings linked below carry the rest. ```yaml condition: - va: 10.0 # apparent wind speed [m/s] + va: 10.0 # apparent wind speed [m/s] alpha: 5.0 # angle of attack [°] beta: 0.0 # sideslip angle [°] yaw_rate: 0.0 # turn rate about the body z axis [°/s] @@ -67,7 +67,7 @@ wings: delta_range: [-40, 10, 40] # flap-deflection sweep [°]; null for no flap sweep # angles off the reference angle a live polar is re-solved at [°] live_offsets: [-12, -9, -6, -3, 0, 3, 6, 9, 12] - va: 25.0 # apparent wind the Reynolds number is taken at [m/s] + va: 25.0 # apparent wind the Reynolds number is taken at [m/s] chord_ref: 1.0 # reference (maximum panel) chord [m] table_format: arrow # per-node table format: csv or arrow diff --git a/examples/linearize_check.jl b/examples/linearize_check.jl index 00a610a0..912a3d59 100644 --- a/examples/linearize_check.jl +++ b/examples/linearize_check.jl @@ -39,10 +39,10 @@ va_vec_b_0 = apparent_wind(aoa_rad, side_slip, va) omega_b_0 = zeros(3) theta_0 = zeros(n_unrefined) -theta_idxs = 1:n_unrefined -va_vec_idxs = (n_unrefined + 1):(n_unrefined + 3) -omega_idxs = (n_unrefined + 4):(n_unrefined + 6) -y0 = [theta_0; va_vec_b_0; omega_b_0] +theta_idxs = 1:n_unrefined +va_vec_idxs = (n_unrefined + 1):(n_unrefined + 3) +omega_idxs = (n_unrefined + 4):(n_unrefined + 6) +y0 = [theta_0; va_vec_b_0; omega_b_0] @info "Computing FiniteDiff Jacobian …" t_fd = @elapsed begin diff --git a/src/solver.jl b/src/solver.jl index 8076e1ed..c121a860 100644 --- a/src/solver.jl +++ b/src/solver.jl @@ -1350,7 +1350,7 @@ function linearize(solver::Solver{<:Any, U}, body_aero::BodyAerodynamics, y::Vec solver_c = solver else shadow = shadow_ref[] - if shadow === nothing || eltype(shadow[1].va_vec) !== TI + if shadow === nothing || eltype(getfield(shadow[1], :va_vec)) !== TI shadow_ref[] = make_dual_shadow(solver, body_aero, TI) end body_aero_c, solver_c = shadow_ref[] diff --git a/test/body_aerodynamics/test_body_aerodynamics.jl b/test/body_aerodynamics/test_body_aerodynamics.jl index ec43443f..b36001ad 100644 --- a/test/body_aerodynamics/test_body_aerodynamics.jl +++ b/test/body_aerodynamics/test_body_aerodynamics.jl @@ -480,6 +480,13 @@ end @test body_aero.va_vec ≈ [11.0, 0.0, 0.0] end +@testset "body_aero.va and panel.va are removed" begin + body_aero = BodyAerodynamics([inviscid_wing([0.0, 1.0, 2.0])]) + set_va!(body_aero, [10.0, 0.0, 0.0]) + @test_throws FieldError body_aero.va + @test_throws FieldError body_aero.panels[1].va +end + @testset "set_va! with omega on multi-wing body" begin body_aero = BodyAerodynamics([inviscid_wing([0.0, 1.0, 2.0]), inviscid_wing([10.0, 11.0, 12.0])]) @@ -495,7 +502,6 @@ end @test body_aero.omega ≈ omega @test !body_aero.has_distributed_va @test body_aero.va_vec ≈ va_vec - @test_throws FieldError body_aero.va new_omega = [0.0, 0.0, 2.0] @test body_aero.va_vec ≈ va_vec