Skip to content
Open
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
2 changes: 1 addition & 1 deletion .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
matrix:
version:
- '1.10'
- '1'
- '1.11'
os:
- ubuntu-latest
build_is_production_build:
Expand Down
20 changes: 0 additions & 20 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,11 @@ VortexStepMethodControlPlotsExt = "ControlPlots"
VortexStepMethodMakieExt = "Makie"

[compat]
Aqua = "0.8"
BenchmarkTools = "1"
CSV = "0.10"
Colors = "0.13"
ControlPlots = "0.2.5"
DataFrames = "1.7"
DefaultApplication = "1"
DelimitedFiles = "1"
DifferentiationInterface = "0.7.4"
Documenter = "1.8"
FiniteDiff = "2.27.0"
Interpolations = "0.15, 0.16"
LaTeXStrings = "1"
Expand All @@ -60,28 +55,13 @@ Parameters = "0.12"
Pkg = "1"
PreallocationTools = "0.4.31"
PrecompileTools = "1.2.1"
Random = "1.10.0"
RecursiveArrayTools = "3 - 3.36.0"
SciMLBase = "2.77.0"
Serialization = "1"
StaticArrays = "1"
Statistics = "1"
StructMapping = "0.2.3"
Test = "1"
Timers = "0.1"
Xfoil = "1.1.0"
YAML = "0.4.13"
julia = "1.10, 1.11"

[extras]
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
ControlPlots = "23c2ee80-7a9e-4350-b264-8e670f12517c"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["Test", "DataFrames", "CSV", "Documenter", "BenchmarkTools", "ControlPlots", "Aqua", "Random"]
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ if you haven't already. On Linux, make sure that Python3 and Matplotlib are inst
```
sudo apt install python3-matplotlib
```
Furthermore, the packages `TestEnv` and `ControlPlots` must be installed globally:
Furthermore, the package `ControlPlots` must be installed globally:
```
julia -e 'using Pkg; Pkg.add("TestEnv"); Pkg.add("ControlPlots")'
julia -e 'using Pkg; Pkg.add("ControlPlots")'
```

Before installing this software it is suggested to create a new project, for example like this:
Expand Down
2 changes: 1 addition & 1 deletion bin/install
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ fi

export JULIA_PKG_SERVER_REGISTRY_PREFERENCE=eager

julia -e 'using Pkg; Pkg.add("TestEnv"); Pkg.add("ControlPlots")'
julia -e 'using Pkg; Pkg.add("ControlPlots")'

julia --project -e 'include("bin/install.jl")'

Expand Down
4 changes: 4 additions & 0 deletions data/ram_air_kite/vsm_settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,17 @@ PanelDistribution:
InitialGammaDistribution:
ELLIPTIC: Elliptic distribution
ZEROS: Constant distribution
PanelGroupingMethod:
EQUAL_SIZE: Divide panels into equally-sized sequential groups
REFINE: Group refined panels by their original unrefined section

wings:
- name: main_wing
n_panels: 40
n_groups: 40
spanwise_panel_distribution: LINEAR
spanwise_direction: [0.0, 1.0, 0.0]
grouping_method: EQUAL_SIZE
remove_nan: true
solver_settings:
n_panels: 40
Expand Down
6 changes: 0 additions & 6 deletions docs/make.jl
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
using Pkg
if ("TestEnv" ∈ keys(Pkg.project().dependencies))
if ! ("Documents" ∈ keys(Pkg.project().dependencies))
using TestEnv; TestEnv.activate()
end
end
using ControlPlots
using VortexStepMethod
using Documenter
Expand Down
1 change: 1 addition & 0 deletions docs/src/glossary.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
| AIC | Aerodynamic Influence Coefficient (AIC). The AIC matrix represents the relationship between the induced velocities or pressures on aerodynamic surfaces and the circulation strength or modal deformations of the lifting surfaces.|
| inviscid | A fluid flow in which viscosity is considered negligible or zero. This means that there is no internal friction between the fluid layers, and the effects of viscosity on the flow are assumed to be insignificant. |
| Panel | Flat surface element in 3D that approximate the contour of the aerodynamic body being studied.|
| Panel Group | A collection of panels whose aerodynamic forces and moments are summed together. Groups can be defined using EQUAL_SIZE (sequential grouping) or REFINE (based on original unrefined structure) methods.|
| Section |A wing section, also known as an airfoil or aerofoil, is the cross-sectional shape of an aircraft wing.|
| Span | Distance from one wing tip to the other wing tip. |
| Polar | The polar typically plots the coefficient of lift (CL) against the coefficient of drag (CD), with the angle of attack as a parameter along the curve. |
Expand Down
4 changes: 2 additions & 2 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ if you haven't already. On Linux, make sure that Python3 and Matplotlib are inst
```
sudo apt install python3-matplotlib
```
Furthermore, the packages `TestEnv` and `ControlPlots` must be installed globally:
Furthermore, the package `ControlPlots` must be installed globally:
```
julia -e 'using Pkg; Pkg.add("TestEnv"); Pkg.add("ControlPlots")'
julia -e 'using Pkg; Pkg.add("ControlPlots")'
```

Before installing this software it is suggested to create a new project, for example like this:
Expand Down
32 changes: 32 additions & 0 deletions docs/src/tips_and_tricks.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,38 @@ The following bodies can be simulated:
To build the geometry of a RAM-air kite, a 3D .obj file can be used as input. In addition a `.dat` file is needed.
It should have two columns, one for the `x` and one for the `y` coordinate of the 2D polar that is used.

## Panel Grouping Methods
When creating a wing, you can specify how panels should be grouped for moment and force calculations using the `grouping_method` parameter. Two methods are available:

### EQUAL_SIZE (Default)
Divides refined panels into equally-sized sequential groups. This is the original behavior.

```julia
wing = Wing(40; n_groups=4, grouping_method=EQUAL_SIZE)
```

In this example, with 40 panels and 4 groups, each group will contain 10 consecutive panels (panels 1-10, 11-20, 21-30, 31-40).

### REFINE
Groups refined panels back to their original unrefined section. This is useful when you want group moments and forces to represent the original wing structure, regardless of panel refinement.

```julia
# Create wing with 4 unrefined sections (3 panels)
wing = Wing(40; n_groups=3, grouping_method=REFINE)
add_section!(wing, [0, 5, 0], [1, 5, 0], INVISCID) # Section 1
add_section!(wing, [0, 2.5, 0], [1, 2.5, 0], INVISCID) # Section 2
add_section!(wing, [0, 0, 0], [1, 0, 0], INVISCID) # Section 3
add_section!(wing, [0, -5, 0], [1, -5, 0], INVISCID) # Section 4
```

**Important:** When using `REFINE`, `n_groups` must equal the number of unrefined panels (number of sections - 1). The solver will automatically map each refined panel to its closest original unrefined panel and sum their moments and forces accordingly.

This is particularly useful for:
- LEI kites where you want loads per rib
- Wings with discrete control surfaces
- Cases where physical structure doesn't align with uniform panel distribution
- Dynamic simulations where you have fewer structural segments than panels needed for accurate VSM aerodynamics. For example, a 6-segment structural model can be combined with 40-panel aerodynamics by using `n_groups=6` and `grouping_method=REFINE` to map aerodynamic loads back to the structural segments.

## RAM-air kite model
If running the example `ram_air_kite.jl` fails, try to run the `cleanup.jl` script and then try again. Background: this example caches the calculated polars. Reading cached polars can fail after an update.

Expand Down
11 changes: 6 additions & 5 deletions docs/src/types.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Model
WingType
AeroModel
PanelDistribution
PanelGroupingMethod
InitialGammaDistribution
SolverStatus
```
Expand All @@ -24,17 +25,17 @@ AeroData
```

## Wing Geometry, Panel and Aerodynamics
A body is constructed of one or more abstract wings. An abstract wing can be a Wing or a RamAirWing.
A Wing/ RamAirWing has one or more sections.
A body is constructed of one or more abstract wings. All wings are of type Wing.
A Wing has one or more sections and can be created from YAML files or OBJ geometry.
```@docs
Section
Section(LE_point::PosVector, TE_point::PosVector, aero_model)
Wing
Wing(n_panels::Int; spanwise_distribution::PanelDistribution=LINEAR,
spanwise_direction::PosVector=MVec3([0.0, 1.0, 0.0]))
RamAirWing
RamAirWing(obj_path, dat_path; alpha=0.0, crease_frac=0.75, wind_vel=10., mass=1.0,
n_panels=54, n_sections=n_panels+1, spanwise_distribution=UNCHANGED,
ObjWing
ObjWing(obj_path, dat_path; alpha=0.0, crease_frac=0.75, wind_vel=10., mass=1.0,
n_panels=54, n_sections=n_panels+1, spanwise_distribution=UNCHANGED,
spanwise_direction=[0.0, 1.0, 0.0])
BodyAerodynamics
```
Expand Down
8 changes: 8 additions & 0 deletions examples/Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[deps]
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
ControlPlots = "23c2ee80-7a9e-4350-b264-8e670f12517c"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
GLMakie = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
VortexStepMethod = "ed3cd733-9f0f-46a9-93e0-89b8d4998dd9"
12 changes: 3 additions & 9 deletions examples/bench.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,6 @@ using LinearAlgebra
using ControlPlots
using VortexStepMethod

using Pkg

if !("CSV" ∈ keys(Pkg.project().dependencies))
using TestEnv
TestEnv.activate()
end

# Step 1: Define wing parameters
n_panels = 20 # Number of panels
Expand Down Expand Up @@ -56,9 +50,9 @@ println("Rectangular wing, solve:")
@time solve(vsm_solver, body_aero, nothing)

# Create wing geometry
wing = RamAirWing(
joinpath("data", "ram_air_kite", "ram_air_kite_body.obj"),
joinpath("data", "ram_air_kite", "ram_air_kite_foil.dat");
wing = ObjWing(
joinpath("data", "ram_air_kite", "ram_air_kite_body.obj"),
joinpath("data", "ram_air_kite", "ram_air_kite_foil.dat");
prn=false
)
body_aero = BodyAerodynamics([wing])
Expand Down
5 changes: 0 additions & 5 deletions examples/menu.jl
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
using Pkg
if ! ("ControlPlots" ∈ keys(Pkg.project().dependencies))
using TestEnv; TestEnv.activate()
end

using ControlPlots
using VortexStepMethod
using REPL.TerminalMenus
Expand Down
12 changes: 6 additions & 6 deletions examples/ram_air_kite.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using ControlPlots
using GLMakie
using VortexStepMethod
using LinearAlgebra

Expand All @@ -9,9 +9,9 @@ DEFORM = false
LINEARIZE = false

# Create wing geometry
wing = RamAirWing(
joinpath("data", "ram_air_kite", "ram_air_kite_body.obj"),
joinpath("data", "ram_air_kite", "ram_air_kite_foil.dat");
wing = ObjWing(
joinpath("data", "ram_air_kite", "ram_air_kite_body.obj"),
joinpath("data", "ram_air_kite", "ram_air_kite_foil.dat");
prn=PRN
)
body_aero = BodyAerodynamics([wing];)
Expand All @@ -21,7 +21,7 @@ println("First init")
if DEFORM
# Linear interpolation of alpha from 10° at one tip to 0° at the other
println("Deform")
@time VortexStepMethod.smooth_deform!(wing, deg2rad.([10,20,10,0]), deg2rad.([-10,0,-10,0]))
@time group_deform!(wing, deg2rad.([10,20,10,0]), deg2rad.([-10,0,-10,0]); smooth=true)
println("Deform init")
@time VortexStepMethod.reinit!(body_aero; init_aero=false)
end
Expand Down Expand Up @@ -118,4 +118,4 @@ PLOT && plot_polars(
is_show=true,
use_tex=USE_TEX
)
nothing
nothing
24 changes: 12 additions & 12 deletions examples/stall_model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@ using ControlPlots
using LinearAlgebra
using VortexStepMethod

using Pkg
if ! ("CSV" ∈ keys(Pkg.project().dependencies))
using TestEnv; TestEnv.activate()
end
using CSV
using DataFrames

Expand Down Expand Up @@ -38,7 +34,9 @@ for row in eachrow(df)
end

# Create wing geometry
CAD_wing = Wing(n_panels; spanwise_distribution)
# Using REFINE grouping method: n_groups should equal number of unrefined panels (18 sections = 18 panels)
n_groups = length(rib_list) - 1
CAD_wing = Wing(n_panels; spanwise_distribution, n_groups, grouping_method=REFINE)
for rib in rib_list
add_section!(CAD_wing, rib[1], rib[2], rib[3], rib[4])
end
Expand Down Expand Up @@ -109,21 +107,23 @@ path_cfd_lebesque = joinpath(
"V3_CL_CD_RANS_Lebesque_2024_Rey_300e4.csv"
)

# Only include literature data if file exists
literature_paths = isfile(path_cfd_lebesque) ? [path_cfd_lebesque] : String[]
labels = isfile(path_cfd_lebesque) ?
["VSM CAD 19ribs", "VSM CAD 19ribs , with stall correction", "CFD_Lebesque Rey 30e5"] :
["VSM CAD 19ribs", "VSM CAD 19ribs , with stall correction"]

PLOT && plot_polars(
[vsm_solver, VSM_with_stall_correction],
[body_aero, body_aero],
[
"VSM CAD 19ribs",
"VSM CAD 19ribs , with stall correction",
"CFD_Lebesque Rey 30e5"
];
literature_path_list=[path_cfd_lebesque],
labels;
literature_path_list=literature_paths,
angle_range=range(0, 25, length=25),
angle_type="angle_of_attack",
angle_of_attack=0,
side_slip=0,
v_a=10,
title="tutorial_testing_stall_model_n_panels_$(n_panels)_distribution_$(spanwise_distribution)",
title="tutorial_testing_stall_model_n_panels_$(n_panels)_distribution_$(spanwise_distribution)_grouping_$(CAD_wing.grouping_method)",
data_type=".pdf",
save_path=joinpath(save_folder, "polars"),
is_save=true,
Expand Down
Loading
Loading