Skip to content

Commit 1599489

Browse files
authored
Merge branch 'main' into CI
2 parents 8aacebe + 7d585ba commit 1599489

File tree

111 files changed

+485
-6005
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

111 files changed

+485
-6005
lines changed

Project.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ authors = ["1-Bart-1 <bart@vandelint.net>"]
44
version = "0.1.0"
55

66
[deps]
7+
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
78
Colors = "5ae59095-9a9b-59fe-a467-6f913c188581"
89
DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab"
910
LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"

src/filament.jl

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -35,35 +35,45 @@ function velocity_3D_bound_vortex!(
3535
filament::BoundFilament,
3636
XVP::Vector{Float64},
3737
gamma::Float64,
38-
core_radius_fraction::Float64
38+
core_radius_fraction::Float64,
39+
work_vectors::NTuple{10, Vector{Float64}}
3940
)
41+
r1, r2, r1Xr2, r1Xr0, r2Xr0, r1r2norm, r1_proj, r2_proj, r1_projXr2_proj, vel_ind_proj = work_vectors
4042
r0 = filament.r0
41-
r1 = XVP - filament.x1
42-
r2 = XVP - filament.x2
43+
r1 .= XVP .- filament.x1
44+
r2 .= XVP .- filament.x2
4345

4446
# Cut-off radius
4547
epsilon = core_radius_fraction * norm(r0)
48+
49+
cross3!(r1Xr2, r1, r2)
50+
cross3!(r1Xr0, r1, r0)
51+
r1r2norm .= r1./norm(r1) .- r2./norm(r2)
4652

4753
# Check point location relative to filament
48-
if norm(cross(r1, r0)) / norm(r0) > epsilon
49-
vel .= (gamma / (4π)) * cross(r1, r2) / (norm(cross(r1, r2))^2) *
50-
dot(r0, r1/norm(r1) - r2/norm(r2))
51-
elseif norm(cross(r1, r0)) / norm(r0) == 0
54+
if norm(r1Xr0) / norm(r0) > epsilon
55+
vel .= (gamma / (4π)) .* r1Xr2 ./ (norm(r1Xr2)^2) .*
56+
dot(r0, r1r2norm)
57+
elseif norm(r1Xr0) / norm(r0) == 0
5258
vel .= zeros(3)
5359
else
5460
@info "inside core radius"
55-
@info "distance from control point to filament: $(norm(cross(r1, r0)) / norm(r0))"
61+
@info "distance from control point to filament: $(norm(r1Xr0) / norm(r0))"
5662

5763
# Project onto core radius
58-
r1_proj = dot(r1, r0) * r0 / (norm(r0)^2) +
59-
epsilon * cross(r1, r0) / norm(cross(r1, r0))
60-
r2_proj = dot(r2, r0) * r0 / (norm(r0)^2) +
61-
epsilon * cross(r2, r0) / norm(cross(r2, r0))
62-
63-
vel_ind_proj = (gamma / (4π)) * cross(r1_proj, r2_proj) / (norm(cross(r1_proj, r2_proj))^2) *
64-
dot(r0, r1_proj/norm(r1_proj) - r2_proj/norm(r2_proj))
65-
66-
vel .= norm(cross(r1, r0)) / (norm(r0) * epsilon) * vel_ind_proj
64+
cross3!(r2Xr0, r2, r0)
65+
r1_proj .= dot(r1, r0) .* r0 ./ (norm(r0)^2) .+
66+
epsilon .* r1Xr0 ./ norm(r1Xr0)
67+
r2_proj .= dot(r2, r0) .* r0 ./ (norm(r0)^2) .+
68+
epsilon .* r2Xr0 ./ norm(r2Xr0)
69+
cross3!(r1_projXr2_proj, r1_proj, r2_proj)
70+
71+
vel_ind_proj .= (gamma / (4π)) .* r1_projXr2_proj ./ (norm(r1_projXr2_proj)^2) .*
72+
dot(r0, r1_proj/norm(r1_proj) .- r2_proj/norm(r2_proj))
73+
74+
@show vel_ind_proj r1_projXr2_proj
75+
76+
vel .= norm(r1Xr0) ./ (norm(r0) * epsilon) .* vel_ind_proj
6777
end
6878
nothing
6979
end

src/panel.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,8 @@ function calculate_velocity_induced_single_ring_semiinfinite(
374374
filament,
375375
evaluation_point,
376376
gamma,
377-
core_radius_fraction
377+
core_radius_fraction,
378+
work_vectors
378379
)
379380
end
380381
elseif i (2, 3) # trailing filaments

test/runtests.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,8 @@ cd("..")
44
println("Running tests...")
55
@testset verbose = true "Testing VortexStepMethod..." begin
66
include("test_bound_filament.jl")
7+
include("test_panel.jl")
8+
include("test_semi_infinite_filament.jl")
9+
include("test_wing_aerodynamics.jl")
10+
include("test_wing_geometry.jl")
711
end

test/test_bound_filament.jl

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using VortexStepMethod: BoundFilament, velocity_3D_bound_vortex!
22
using LinearAlgebra
3+
using BenchmarkTools: @benchmarkable
34
using Test
45

56
# Test helper functions
@@ -27,6 +28,25 @@ end
2728
gamma = 1.0
2829
core_radius_fraction = 0.01
2930
induced_velocity = zeros(3)
31+
work_vectors = ntuple(_ -> Vector{Float64}(undef, 3), 10)
32+
33+
@testset "Non-allocating" begin
34+
filament = create_test_filament()
35+
control_point = [0.5, 1.0, 0.0]
36+
induced_velocity = zeros(3)
37+
38+
b = @benchmarkable velocity_3D_bound_vortex!(
39+
$induced_velocity,
40+
$filament,
41+
$control_point,
42+
$gamma,
43+
$core_radius_fraction,
44+
$work_vectors
45+
)
46+
result = run(b)
47+
@test result.allocs == 0
48+
@test result.memory == 0
49+
end
3050

3151
@testset "Calculate Induced Velocity" begin
3252
filament = create_test_filament()
@@ -37,7 +57,8 @@ end
3757
filament,
3858
control_point,
3959
gamma,
40-
core_radius_fraction
60+
core_radius_fraction,
61+
work_vectors
4162
)
4263
analytical_velocity = analytical_solution(control_point, gamma)
4364

@@ -58,7 +79,8 @@ end
5879
filament,
5980
point,
6081
gamma,
61-
core_radius_fraction
82+
core_radius_fraction,
83+
work_vectors
6284
)
6385
@test all(isapprox.(induced_velocity, zeros(3), atol=1e-10))
6486
@test !any(isnan.(induced_velocity))
@@ -74,9 +96,9 @@ end
7496
filament,
7597
control_point,
7698
gamma,
77-
core_radius_fraction
99+
core_radius_fraction,
100+
work_vectors
78101
)
79-
80102
@test !any(isnan.(induced_velocity))
81103
@test isapprox(induced_velocity[1], 0.0, atol=1e-8)
82104
@test abs(induced_velocity[2]) < 1e-8
@@ -92,7 +114,8 @@ end
92114
filament,
93115
control_point,
94116
gamma,
95-
core_radius_fraction
117+
core_radius_fraction,
118+
work_vectors
96119
)
97120

98121
@test !any(isnan.(induced_velocity))
@@ -105,9 +128,9 @@ end
105128
filament = create_test_filament()
106129
control_point = [0.5, 1.0, 0.0]
107130

108-
velocity_3D_bound_vortex!(v1, filament, control_point, 1.0, core_radius_fraction)
109-
velocity_3D_bound_vortex!(v2, filament, control_point, 2.0, core_radius_fraction)
110-
velocity_3D_bound_vortex!(v4, filament, control_point, 4.0, core_radius_fraction)
131+
velocity_3D_bound_vortex!(v1, filament, control_point, 1.0, core_radius_fraction, work_vectors)
132+
velocity_3D_bound_vortex!(v2, filament, control_point, 2.0, core_radius_fraction, work_vectors)
133+
velocity_3D_bound_vortex!(v4, filament, control_point, 4.0, core_radius_fraction, work_vectors)
111134

112135
@test isapprox(v4, 2 * v2)
113136
@test isapprox(v4, 4 * v1)
@@ -116,8 +139,8 @@ end
116139
@testset "Symmetry" begin
117140
filament = BoundFilament([-1.0, 0.0, 0.0], [1.0, 0.0, 0.0])
118141

119-
velocity_3D_bound_vortex!(v1, filament, [0.0, 1.0, 0.0], gamma, core_radius_fraction)
120-
velocity_3D_bound_vortex!(v2, filament, [0.0, -1.0, 0.0], gamma, core_radius_fraction)
142+
velocity_3D_bound_vortex!(v1, filament, [0.0, 1.0, 0.0], gamma, core_radius_fraction, work_vectors)
143+
velocity_3D_bound_vortex!(v2, filament, [0.0, -1.0, 0.0], gamma, core_radius_fraction, work_vectors)
121144

122145
@test isapprox(v1, -v2)
123146
end
@@ -134,7 +157,7 @@ end
134157

135158
velocities = [zeros(3) for p in points]
136159
[
137-
velocity_3D_bound_vortex!(velocities[i], filament, p, gamma, core_radius_fraction)
160+
velocity_3D_bound_vortex!(velocities[i], filament, p, gamma, core_radius_fraction, work_vectors)
138161
for (i, p) in enumerate(points)
139162
]
140163

@@ -147,7 +170,7 @@ end
147170
@test norm(velocities[2]) > norm(velocities[3])
148171

149172
# Check continuity around core radius
150-
@test_broken isapprox(velocities[1], velocities[2], rtol=1e-3)
173+
@test isapprox(velocities[1], velocities[2], rtol=1e-2)
151174

152175
# Check non-zero velocities
153176
@test !all(isapprox.(velocities[1], zeros(3), atol=1e-10))
@@ -161,7 +184,8 @@ end
161184
filament,
162185
[0.5, -core_radius_fraction, 0.0],
163186
gamma,
164-
core_radius_fraction
187+
core_radius_fraction,
188+
work_vectors
165189
)
166190
@test isapprox(velocities[2], -v_neg)
167191
end

test/test_wing_aerodynamics.jl

Lines changed: 146 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ include("utils.jl")
6363
cd_cm = calculate_cd_cm(panel, alpha[i])
6464
drag[i] = dyn_visc * cd_cm[1] * panel.chord
6565
moment[i] = dyn_visc * cd_cm[2] * panel.chord^2
66-
@info "lift: $lift, drag: $drag, moment: $moment"
66+
# @info "lift: $lift, drag: $drag, moment: $moment"
6767
end
6868
Fmag = hcat(lift, drag, moment)
6969

@@ -104,7 +104,6 @@ include("utils.jl")
104104
@test length(results_NEW["cd_distribution"]) == length(wing_aero.panels)
105105
end
106106

107-
108107
@testset "Induction Matrix Creation" begin
109108
# Setup
110109
n_panels = 3
@@ -206,6 +205,149 @@ end
206205
@test isapprox(MatrixU, AIC_x, atol=1e-8)
207206
@test isapprox(MatrixV, -AIC_y, atol=1e-8)
208207
@test isapprox(MatrixW, AIC_z, atol=1e-8)
209-
@show MatrixU MatrixV MatrixW
210208
end
211-
end
209+
end
210+
211+
212+
@testset "Wing Geometry Creation" begin
213+
function create_geometry(; model="VSM", wing_type="rectangular", plotting=false, N=40)
214+
max_chord = 1.0
215+
span = 17.0
216+
AR = span^2 /* span * max_chord / 4)
217+
@debug "AR: $AR"
218+
Umag = 20.0
219+
aoa = 5.7106 * π / 180
220+
Uinf = [cos(aoa), 0.0, sin(aoa)] .* Umag
221+
222+
coord = if wing_type == "rectangular"
223+
twist = range(-0.5, 0.5, length=N)
224+
beta = range(-2, 2, length=N)
225+
generate_coordinates_rect_wing(
226+
fill(max_chord, N),
227+
span,
228+
twist,
229+
beta,
230+
N,
231+
"lin"
232+
)
233+
elseif wing_type == "curved"
234+
generate_coordinates_curved_wing(
235+
max_chord, span, π/4, 5, N, "cos"
236+
)
237+
elseif wing_type == "elliptical"
238+
generate_coordinates_el_wing(max_chord, span, N, "cos")
239+
else
240+
error("Invalid wing type")
241+
end
242+
243+
coord_left_to_right = flip_created_coord_in_pairs(deepcopy(coord))
244+
wing = Wing(N; spanwise_panel_distribution="unchanged")
245+
for i in 1:2:size(coord_left_to_right, 1)
246+
add_section!(
247+
wing,
248+
coord_left_to_right[i,:],
249+
coord_left_to_right[i+1,:],
250+
"inviscid"
251+
)
252+
end
253+
wing_aero = WingAerodynamics([wing])
254+
set_va!(wing_aero, (Uinf, 0.0))
255+
256+
return wing_aero, coord, Uinf, model
257+
end
258+
259+
for model in ["VSM", "LLT"]
260+
@debug "model: $model"
261+
for wing_type in ["rectangular", "curved", "elliptical"]
262+
@debug "wing_type: $wing_type"
263+
wing_aero, coord, Uinf, model = create_geometry(
264+
model=model, wing_type=wing_type
265+
)
266+
267+
# Generate geometry
268+
expected_controlpoints, expected_rings, expected_bladepanels,
269+
expected_ringvec, expected_coord_L = create_geometry_general(
270+
coord, Uinf, div(size(coord,1), 2), "5fil", model
271+
)
272+
273+
for i in 1:length(wing_aero.panels)
274+
@debug "i: $i"
275+
# Handle control points
276+
index_reversed = length(wing_aero.panels) - i + 1
277+
panel = wing_aero.panels[index_reversed]
278+
279+
evaluation_point = if model == "VSM"
280+
panel.control_point
281+
else # LLT
282+
panel.aerodynamic_center
283+
end
284+
285+
@test isapprox(evaluation_point, expected_controlpoints[i]["coordinates"], atol=1e-4)
286+
@test isapprox(panel.chord, expected_controlpoints[i]["chord"], atol=1e-4)
287+
@test isapprox(panel.x_airf, expected_controlpoints[i]["normal"], atol=1e-4)
288+
@test isapprox(panel.y_airf, expected_controlpoints[i]["tangential"], atol=1e-4)
289+
@test isapprox(
290+
hcat(panel.x_airf, panel.y_airf, panel.z_airf),
291+
expected_controlpoints[i]["airf_coord"],
292+
atol=1e-4
293+
)
294+
295+
if model == "VSM"
296+
@test isapprox(
297+
panel.aerodynamic_center,
298+
expected_controlpoints[i]["coordinates_aoa"],
299+
atol=1e-4
300+
)
301+
end
302+
303+
# Handle rings
304+
expected_ring_i = expected_rings[i]
305+
expected_ring_i_list = [
306+
expected_ring_i[1],
307+
expected_ring_i[2],
308+
expected_ring_i[3],
309+
expected_ring_i[4],
310+
expected_ring_i[5]
311+
]
312+
313+
filaments = panel.filaments
314+
filament_list = [
315+
filaments[1],
316+
filaments[3],
317+
filaments[5],
318+
filaments[2],
319+
filaments[4]
320+
]
321+
322+
for (j, fil) in enumerate(filament_list)
323+
if j == 1 # bound filaments
324+
@test isapprox(fil.x1, expected_ring_i_list[j]["x1"], atol=1e-4)
325+
@test isapprox(fil.x2, expected_ring_i_list[j]["x2"], atol=1e-4)
326+
elseif j (2, 4) # trailing filaments
327+
@test isapprox(fil.x1, expected_ring_i_list[j]["x1"], atol=1e-4)
328+
@test isapprox(fil.x2, expected_ring_i_list[j]["x2"], atol=1e-4)
329+
else # semi-infinite filaments
330+
@test isapprox(fil.x1, expected_ring_i_list[j]["x1"], atol=1e-4)
331+
end
332+
end
333+
334+
# Handle bladepanels
335+
exp_bladepanels = expected_bladepanels[i]
336+
@test isapprox(panel.LE_point_2, exp_bladepanels["p1"], atol=1e-4)
337+
@test isapprox(panel.LE_point_1, exp_bladepanels["p2"], atol=1e-4)
338+
@test isapprox(panel.TE_point_1, exp_bladepanels["p3"], atol=1e-4)
339+
@test isapprox(panel.TE_point_2, exp_bladepanels["p4"], atol=1e-4)
340+
341+
# Handle ringvec
342+
exp_ringvec = expected_ringvec[i]
343+
r0 = panel.bound_point_1 - panel.bound_point_2
344+
r3 = evaluation_point - (panel.bound_point_1 + panel.bound_point_2) / 2
345+
@test isapprox(r0, exp_ringvec["r0"], atol=1e-4)
346+
@test isapprox(r3, exp_ringvec["r3"], atol=1e-4)
347+
348+
# Handle coord_L
349+
@test all(isapprox.(panel.aerodynamic_center, expected_coord_L[:, i]))
350+
end
351+
end
352+
end
353+
end

0 commit comments

Comments
 (0)