Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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`
Expand Down
2 changes: 1 addition & 1 deletion data/TUDELFT_V3_KITE/vsm_settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion data/TUDELFT_V3_KITE/vsm_settings_coarse.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion data/pyramid_model/vsm_settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion docs/src/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -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,
)
Expand Down
6 changes: 3 additions & 3 deletions docs/src/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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.
8 changes: 4 additions & 4 deletions examples/V3_kite.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion examples/V3_neuralfoil.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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,
)
Expand Down
6 changes: 3 additions & 3 deletions examples/billowing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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,
Expand Down
14 changes: 7 additions & 7 deletions examples/linearize_check.jl
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,16 @@ 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_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
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),
)
Expand All @@ -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(),
)
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion examples/obj_to_yaml_kite.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
6 changes: 3 additions & 3 deletions examples/pyramid_model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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,
Expand 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,
Expand Down
2 changes: 1 addition & 1 deletion examples/ram_air_kite.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion examples/rectangular_wing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion examples/stall_model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
24 changes: 12 additions & 12 deletions ext/VortexStepMethodMakieExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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)

Expand All @@ -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)
Expand All @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -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)
Expand All @@ -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,
Expand Down Expand Up @@ -1220,18 +1220,18 @@ 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)
if !isnothing(angle_of_attack_for_spanwise_distribution)
α_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)
Expand Down Expand Up @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion mwes/mwe_01.jl
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion mwes/mwe_warntype.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)
4 changes: 2 additions & 2 deletions src/VortexStepMethod.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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`)
Expand Down Expand Up @@ -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`)
Expand Down
Loading
Loading