Skip to content

Commit aa47b29

Browse files
ufechner71-Bart-1
andauthored
Refactoring, one bugfix (#130)
* Bugfix * add mwe_03.jl * Update mwe_03.jl * Add and use PrecompileTools * Update mwe_03.jl * Update mwe_03.jl * Add y to BodyAerodynamics * Reduce allocations to 85 * Improve comments. * Update comments * Add enum WingType * Use ==, not === for enums * Adjust test tolerances * Tests pass * Add TODO * First fix * Second step * No coverage for production tests * Next try * Add code coverage job * Fix * Next try * Do not test on nightly * Improve mwe_03.jl * New file precompile.jl * Fix tests --------- Co-authored-by: Uwe Fechner <[email protected]> Co-authored-by: 1-Bart-1 <[email protected]>
1 parent de95480 commit aa47b29

File tree

16 files changed

+221
-44
lines changed

16 files changed

+221
-44
lines changed

.github/workflows/CI.yml

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,19 @@ jobs:
2424
- 'pre'
2525
os:
2626
- ubuntu-latest
27+
build_is_production_build:
28+
- true
2729
arch:
2830
- x64
2931
include:
3032
- os: windows-latest
3133
arch: x64
3234
version: 1
35+
build_is_production_build: true
3336
- os: macOS-latest
3437
arch: aarch64
3538
version: 1
39+
build_is_production_build: true
3640
steps:
3741
- name: Install matplotlib
3842
run: if [ "$RUNNER_OS" = "Linux" ]; then sudo apt-get install -y python3-matplotlib; fi
@@ -54,11 +58,45 @@ jobs:
5458
${{ runner.os }}-
5559
- uses: julia-actions/julia-buildpkg@v1
5660
- uses: julia-actions/julia-runtest@v1
57-
- uses: julia-actions/julia-processcoverage@v1
58-
- uses: codecov/codecov-action@v5
61+
env:
62+
BUILD_IS_PRODUCTION_BUILD: ${{ matrix.build_is_production_build }}
5963
with:
60-
files: lcov.info
61-
token: ${{ secrets.CODECOV_TOKEN }}
64+
coverage: false
65+
- uses: julia-actions/julia-processcoverage@v1
66+
test-with-code-coverage:
67+
name: Julia ${{ matrix.julia_version }} - ${{ matrix.os }} - ${{ matrix.julia_arch }} - with code coverage
68+
timeout-minutes: 20
69+
strategy:
70+
fail-fast: false
71+
matrix:
72+
julia_version:
73+
- "1.10"
74+
- "1.11"
75+
- "pre"
76+
julia_arch:
77+
- x64
78+
os:
79+
- ubuntu-latest
80+
runs-on: ${{ matrix.os }}
81+
steps:
82+
- name: Install matplotlib
83+
run: if [ "$RUNNER_OS" = "Linux" ]; then sudo apt-get install -y python3-matplotlib; fi
84+
shell: bash
85+
- uses: actions/checkout@v4
86+
- uses: julia-actions/setup-julia@v2
87+
with:
88+
arch: ${{ matrix.julia_arch }}
89+
version: ${{ matrix.julia_version }}
90+
- uses: julia-actions/cache@v2
91+
- uses: julia-actions/julia-runtest@v1
92+
env:
93+
BUILD_IS_PRODUCTION_BUILD: false
94+
- uses: julia-actions/julia-processcoverage@v1
95+
- uses: codecov/codecov-action@v5
96+
with:
97+
token: ${{ secrets.CODECOV_TOKEN }}
98+
files: lcov.info
99+
continue-on-error: true
62100
docs:
63101
name: Documentation
64102
runs-on: ubuntu-latest
@@ -75,5 +113,3 @@ jobs:
75113
env:
76114
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
77115
DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }}
78-
79-

Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ NonlinearSolve = "8913a72c-1f9b-4ce2-8d82-65094dcecaec"
1616
Parameters = "d96e819e-fc66-5662-9728-84c9c7592b0a"
1717
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
1818
PreallocationTools = "d236fae5-4411-538c-8e31-a6e3d9e00b46"
19+
PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a"
1920
Serialization = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
2021
SharedArrays = "1a1011a3-84de-559e-8e89-a11a2f7dc383"
2122
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
@@ -49,6 +50,7 @@ NonlinearSolve = "4"
4950
Parameters = "0.12"
5051
Pkg = "1"
5152
PreallocationTools = "0.4.25"
53+
PrecompileTools = "1.2.1"
5254
Serialization = "1"
5355
SharedArrays = "1"
5456
StaticArrays = "1"

docs/src/types.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ CurrentModule = VortexStepMethod
44
## Enumerations
55
```@docs
66
Model
7+
WingType
78
AeroModel
89
PanelDistribution
910
InitialGammaDistribution

mwes/mwe_03.jl

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Fix allocations of this array comprehension:
2+
# y = [panel.control_point[2] for panel in body_aero.panels]
3+
# This mwe shows that the line above is allocating a lot,
4+
# and provides the function test_new() that shows a better way of implementing.
5+
6+
using VortexStepMethod, PreallocationTools
7+
8+
# Step 1: Define wing parameters
9+
n_panels = 20 # Number of panels
10+
span = 20.0 # Wing span [m]
11+
chord = 1.0 # Chord length [m]
12+
v_a = 20.0 # Magnitude of inflow velocity [m/s]
13+
density = 1.225 # Air density [kg/m³]
14+
alpha_deg = 30.0 # Angle of attack [degrees]
15+
alpha = deg2rad(alpha_deg)
16+
17+
# Step 2: Create wing geometry with linear panel distribution
18+
wing = Wing(n_panels, spanwise_panel_distribution=LINEAR)
19+
20+
# Add wing sections - defining only tip sections with inviscid airfoil model
21+
add_section!(wing,
22+
[0.0, span/2, 0.0], # Left tip LE
23+
[chord, span/2, 0.0], # Left tip TE
24+
INVISCID)
25+
add_section!(wing,
26+
[0.0, -span/2, 0.0], # Right tip LE
27+
[chord, -span/2, 0.0], # Right tip TE
28+
INVISCID)
29+
30+
# Step 3: Initialize aerodynamics
31+
body_aero::BodyAerodynamics = BodyAerodynamics([wing])
32+
33+
y = [panel.control_point[2] for panel in body_aero.panels]
34+
n = @allocated y = [panel.control_point[2] for panel in body_aero.panels]
35+
36+
function test_old(body_aero, gamma_i)
37+
y = [panel.control_point[2] for panel in body_aero.panels]
38+
y
39+
end
40+
41+
function test_new(body_aero, gamma_i)
42+
y = body_aero.y
43+
for (i, panel) in pairs(body_aero.panels)
44+
y[i] = panel.control_point[2]
45+
end
46+
y
47+
end
48+
49+
50+
gamma_i=zeros(length(body_aero.panels))
51+
52+
# make sure the two test functions get compiled
53+
test_old(body_aero, gamma_i)
54+
test_new(body_aero, gamma_i)
55+
56+
println("Old function, using an array comprehension:")
57+
n = @allocated test_old(body_aero, gamma_i)
58+
println("Allocations: ", n)
59+
60+
println("New function, using a pre-allocated array and a for loop:")
61+
m = @allocated test_new(body_aero, gamma_i)
62+
println("Allocations: ", m)

src/VortexStepMethod.jl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ using Parameters
1616
using Serialization
1717
using SharedArrays
1818
using PreallocationTools
19+
using PrecompileTools
1920
using Pkg
2021

2122
# Export public interface
@@ -76,6 +77,18 @@ Enumeration of the implemented model types.
7677
"""
7778
@enum Model VSM LLT
7879

80+
"""
81+
WingType `RECTANGULAR` `CURVED` `ELLIPTICAL`
82+
83+
Enumeration of the implemented wing types.
84+
85+
# Elements:
86+
- RECTANGULAR
87+
- CURVED
88+
- ELLIPTICAL
89+
"""
90+
@enum WingType RECTANGULAR CURVED ELLIPTICAL
91+
7992
"""
8093
AeroModel `LEI_AIRFOIL_BREUKELS` `POLAR_VECTORS` `POLAR_MATRICES` `INVISCID`
8194
@@ -241,5 +254,7 @@ include("panel.jl")
241254
include("body_aerodynamics.jl")
242255
include("wake.jl")
243256
include("solver.jl")
257+
include("precompile.jl")
258+
244259

245260
end # module

src/body_aerodynamics.jl

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,23 @@ Main structure for calculating aerodynamic properties of bodies.
55
66
# Fields
77
- panels::Vector{Panel}: Vector of [Panel](@ref) structs
8-
- wings::Vector{AbstractWing}: A vector of wings; a body can have multiple wings
8+
- wings::Union{Vector{Wing}, Vector{RamAirWing}}: A vector of wings; a body can have multiple wings
99
- `_va`::MVec3 = zeros(MVec3): A vector of the apparent wind speed, see: [MVec3](@ref)
1010
- `omega`::MVec3 = zeros(MVec3): A vector of the turn rates around the kite body axes
1111
- `gamma_distribution`::Vector{Float64}=zeros(Float64, P): A vector of the circulation
1212
of the velocity field; Length: Number of segments. [m²/s]
13-
- `alpha_uncorrected`::Vector{Float64}=zeros(Float64, P): unclear, please define
14-
- `alpha_corrected`::Vector{Float64}=zeros(Float64, P): unclear, please define
15-
- `stall_angle_list`::Vector{Float64}=zeros(Float64, P): unclear, please define
13+
- `alpha_uncorrected`::Vector{Float64}=zeros(Float64, P): angles of attack per panel
14+
- `alpha_corrected`::Vector{Float64}=zeros(Float64, P): corrected angles of attack per panel
15+
- `stall_angle_list`::Vector{Float64}=zeros(Float64, P): stall angle per panel
1616
- alpha_array::Vector{Float64} = zeros(Float64, P)
1717
- v_a_array::Vector{Float64} = zeros(Float64, P)
18-
- work_vectors::NTuple{10,MVec3} = ntuple(_ -> zeros(MVec3), 10)
18+
- work_vectors::NTuple{10, MVec3} = ntuple(_ -> zeros(MVec3), 10)
1919
- AIC::Array{Float64, 3} = zeros(3, P, P)
2020
- projected_area::Float64 = 1.0: The area projected onto the xy-plane of the kite body reference frame [m²]
2121
"""
2222
@with_kw mutable struct BodyAerodynamics{P}
2323
panels::Vector{Panel}
24-
wings::Vector{AbstractWing}
24+
wings::Union{Vector{Wing}, Vector{RamAirWing}}
2525
_va::MVec3 = zeros(MVec3)
2626
omega::MVec3 = zeros(MVec3)
2727
gamma_distribution::Vector{Float64} = zeros(Float64, P)
@@ -33,6 +33,7 @@ Main structure for calculating aerodynamic properties of bodies.
3333
work_vectors::NTuple{10,MVec3} = ntuple(_ -> zeros(MVec3), 10)
3434
AIC::Array{Float64, 3} = zeros(3, P, P)
3535
projected_area::Float64 = one(Float64)
36+
y::Vector{Float64} = zeros(Float64, P)
3637
end
3738

3839
"""
@@ -355,8 +356,10 @@ function calculate_circulation_distribution_elliptical_wing(gamma_i, body_aero::
355356
@debug "Wing span: $wing_span"
356357

357358
# Calculate y-coordinates of control points
358-
# TODO: pre-allocate y
359-
y = [panel.control_point[2] for panel in body_aero.panels]
359+
y = body_aero.y
360+
for (i, panel) in pairs(body_aero.panels)
361+
y[i] = panel.control_point[2]
362+
end
360363

361364
# Calculate elliptical distribution
362365
gamma_i .= gamma_0 * sqrt.(1 .- (2 .* y ./ wing_span).^2)
@@ -544,7 +547,7 @@ function calculate_results(
544547
moment = reshape((cm_array .* 0.5 .* density .* v_a_array.^2 .* chord_array), :, 1)
545548

546549
# Calculate alpha corrections based on model type
547-
if aerodynamic_model_type === VSM
550+
if aerodynamic_model_type == VSM
548551
update_effective_angle_of_attack!(
549552
alpha_corrected,
550553
body_aero,

src/panel.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ function init_aero!(
121121
# Validate aero model consistency
122122
panel.aero_model = section_1.aero_model
123123
aero_model_2 = section_2.aero_model
124-
if !(panel.aero_model === aero_model_2)
124+
if !(panel.aero_model == aero_model_2)
125125
throw(ArgumentError("Both sections must have the same aero model, not $(panel.aero_model) and $aero_model_2"))
126126
end
127127

@@ -174,7 +174,7 @@ function init_aero!(
174174
throw(ArgumentError("Polar data in wrong format: $aero_1"))
175175
end
176176

177-
elseif !(panel.aero_model === INVISCID)
177+
elseif !(panel.aero_model == INVISCID)
178178
throw(ArgumentError("Unsupported aero model: $(panel.aero_model)"))
179179
end
180180
end

src/plotting.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -859,7 +859,7 @@ function VortexStepMethod.plot_polar_data(body_aero::BodyAerodynamics;
859859
is_show = true,
860860
use_tex = false
861861
)
862-
if body_aero.panels[1].aero_model === POLAR_MATRICES
862+
if body_aero.panels[1].aero_model == POLAR_MATRICES
863863
set_plot_style()
864864

865865
# Create figure with subplots

src/precompile.jl

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
@setup_workload begin
2+
# Putting some things in `@setup_workload` instead of `@compile_workload` can reduce the size of the
3+
# precompile file and potentially make loading faster.
4+
# list = [OtherType("hello"), OtherType("world!")]
5+
path = dirname(pathof(@__MODULE__))
6+
7+
@compile_workload begin
8+
# all calls in this block will be precompiled, regardless of whether
9+
# they belong to your package or not (on Julia 1.8 and higher)
10+
# Step 1: Define wing parameters
11+
n_panels = 20 # Number of panels
12+
span = 20.0 # Wing span [m]
13+
chord = 1.0 # Chord length [m]
14+
v_a = 20.0 # Magnitude of inflow velocity [m/s]
15+
density = 1.225 # Air density [kg/m³]
16+
alpha_deg = 30.0 # Angle of attack [degrees]
17+
alpha = deg2rad(alpha_deg)
18+
19+
# Step 2: Create wing geometry with linear panel distribution
20+
wing = Wing(n_panels, spanwise_panel_distribution=LINEAR)
21+
22+
# Add wing sections - defining only tip sections with inviscid airfoil model
23+
add_section!(wing,
24+
[0.0, span/2, 0.0], # Left tip LE
25+
[chord, span/2, 0.0], # Left tip TE
26+
INVISCID)
27+
add_section!(wing,
28+
[0.0, -span/2, 0.0], # Right tip LE
29+
[chord, -span/2, 0.0], # Right tip TE
30+
INVISCID)
31+
32+
# Step 3: Initialize aerodynamics
33+
body_aero::BodyAerodynamics = BodyAerodynamics([wing])
34+
35+
gamma_initial = zeros(length(body_aero.panels))
36+
calculate_circulation_distribution_elliptical_wing(gamma_initial, body_aero)
37+
38+
nothing
39+
end
40+
end

src/solver.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ function solve_base!(solver::Solver, body_aero::BodyAerodynamics, gamma_distribu
385385
# Initialize gamma distribution
386386
gamma_initial = cache_base[1][solver.sol.chord_array]
387387
if isnothing(gamma_distribution)
388-
if solver.type_initial_gamma_distribution === :elliptic
388+
if solver.type_initial_gamma_distribution == ELLIPTIC
389389
calculate_circulation_distribution_elliptical_wing(gamma_initial, body_aero)
390390
else
391391
gamma_initial .= 0

0 commit comments

Comments
 (0)