Skip to content

Commit 40b9352

Browse files
committed
before testing
1 parent d0d968b commit 40b9352

File tree

4 files changed

+105
-80
lines changed

4 files changed

+105
-80
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ Manifest.toml
22
.vscode/settings.json
33
venv
44
results/TUDELFT_V3_LEI_KITE/polars/$C_L$ vs $C_D$.pdf
5+
*.bin
6+

examples/ram_air_kite.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ using DataFrames
55
using LinearAlgebra
66

77
# Create wing geometry
8-
wing = KiteWing("data/HL5_ram_air_kite_body.obj", "data/centre_line_with_profile.dat")
8+
wing = KiteWing("data/HL5_ram_air_kite_body.obj", "data/centre_line_profile_with_billow.dat")
99

1010
# for gamma in range(wing.gamma_tip - wing.gamma_tip/10, -wing.gamma_tip + wing.gamma_tip/10, 20)
1111
# add_section!(wing, gamma, ("dat_file", "data/centre_line_with_profile.dat"))

src/kite_geometry.jl

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,13 @@ function find_circle_center_and_radius(vertices)
3838
end
3939
@show v_min
4040

41-
# Find vertex furthest in y, -z direction
41+
# Find vertex furthest in -y, -z direction
4242
max_score = -Inf
4343
v_tip .= 0.0
4444
for v in vertices
45-
# Score each vertex based on y and -z components
46-
# Higher y and lower z gives higher score
47-
score = v[2] - v[3] # y - z
45+
# Score each vertex based on -y and -z components
46+
# lower y and lower z gives higher score
47+
score = -v[2] - v[3] # - y - z
4848
if score > max_score
4949
max_score = score
5050
v_tip .= v
@@ -66,13 +66,14 @@ function find_circle_center_and_radius(vertices)
6666
z = result[1]
6767

6868
gamma_tip = atan(-v_tip[2], (v_tip[3] - z))
69+
@assert gamma_tip > 0.0
6970

7071
return z, r[1], gamma_tip
7172
end
7273

7374
# Create interpolations for max and min x coordinates
7475
function create_interpolations(vertices, circle_center_z, radius, gamma_tip)
75-
gamma_range = range(-abs(gamma_tip)+1e-6, abs(gamma_tip)-1e-6, 100)
76+
gamma_range = range(-gamma_tip+1e-6, gamma_tip-1e-6, 100)
7677
vz_centered = [v[3] - circle_center_z for v in vertices]
7778

7879
max_xs = zeros(length(gamma_range))
@@ -204,7 +205,7 @@ mutable struct KiteWing <: AbstractWing
204205
te_interp::Function
205206
area_interp::Function
206207

207-
function KiteWing(obj_path, dat_path=nothing; mass=1.0, n_panels=54, spanwise_panel_distribution="linear", spanwise_direction=[0.0, 1.0, 0.0])
208+
function KiteWing(obj_path, foil_path=nothing; n_sections=20, crease_frac=0.75, wind_vel=10., mass=1.0, n_panels=54, spanwise_panel_distribution="linear", spanwise_direction=[0.0, 1.0, 0.0])
208209
!isapprox(spanwise_direction, [0.0, 1.0, 0.0]) && @error "Spanwise direction has to be [0.0, 1.0, 0.0]"
209210
if !isfile(obj_path)
210211
error("OBJ file not found: $obj_path")
@@ -220,8 +221,19 @@ mutable struct KiteWing <: AbstractWing
220221
area_interp = (γ) -> area_interp_(γ)
221222

222223
sections = Section[]
223-
if !isnothing(dat_path)
224-
224+
if !endswith(foil_path, ".dat")
225+
foil_path *= ".dat"
226+
end
227+
polar_path = foil_file[1:end-4] * "_polar.bin"
228+
if !isnothing(foil_path) && !ispath(polar_path)
229+
width = 2gamma_tip * radius
230+
(cl_interp, cd_interp, cm_interp) =
231+
distributed_create_polars(foil_path, polar_path, wind_vel, area_interp(gamma_tip), width, crease_frac)
232+
elseif !isnothing(foil_path) && ispath(polar_path)
233+
(cl_interp, cd_interp, cm_interp) = deserialize(polar_path)
234+
end
235+
for gamma in range(-gamma_tip, gamma_tip, n_sections)
236+
add_section!(wing, gamma, ("interpolations", (cl_interp, cd_interp, cm_interp)))
225237
end
226238
new(
227239
n_panels, spanwise_panel_distribution, spanwise_direction, sections,

src/polars.jl

Lines changed: 82 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
using Distributed, Timers, Serialization, SharedArrays
2-
using Xfoil
3-
using Pkg
4-
using ControlPlots
1+
# using Distributed, Timers, Serialization, SharedArrays
2+
# using Xfoil
3+
# using Pkg
4+
# using ControlPlots
55

6-
function distributed_create_polars(foil_file, v_wind, middle_length, tip_length)
6+
function distributed_create_polars(foil_path, polar_path, v_wind, area, width, x_turn)
77
procs = addprocs()
88

99
function normalize!(x, y)
@@ -20,7 +20,6 @@ function distributed_create_polars(foil_file, v_wind, middle_length, tip_length)
2020

2121
function turn_trailing_edge!(angle, x, y, lower_turn, upper_turn)
2222
theta = deg2rad(angle)
23-
x_turn = 0.75
2423
turn_distance = upper_turn - lower_turn
2524
smooth_idx = []
2625
rm_idx = []
@@ -57,60 +56,26 @@ function distributed_create_polars(foil_file, v_wind, middle_length, tip_length)
5756
nothing
5857
end
5958

60-
function calculate_constants(d_trailing_edge_angle_, x_, y_, cp, lower, upper)
61-
d_trailing_edge_angle = deg2rad(d_trailing_edge_angle_)
62-
x = deepcopy(x_)
63-
y = deepcopy(y_)
64-
c_te = 0.0
65-
if d_trailing_edge_angle > 0
66-
x_ref, y_ref = 0.75, upper
67-
else
68-
x_ref, y_ref = 0.75, lower
69-
end
70-
71-
# straighten out the trailing_edge in order to find the trailing edge torque constant
72-
for i in eachindex(x)
73-
x_rel = x[i] - x_ref
74-
y_rel = y[i] - y_ref
75-
x[i] = x_ref + x_rel * cos(-d_trailing_edge_angle) + y_rel * sin(-d_trailing_edge_angle)
76-
y[i] = y_ref - x_rel * sin(-d_trailing_edge_angle) + y_rel * cos(-d_trailing_edge_angle)
77-
end
78-
79-
x2 = []
80-
y2 = []
81-
for i in 1:(length(x)-1)
82-
if x[i] > x_ref && lower < y[i] < upper
83-
push!(x2, x[i])
84-
push!(y2, y[i])
85-
dx = x[i+1] - x[i]
86-
cp_avg = (cp[i] + cp[i+1]) / 2
87-
c_te -= dx * cp_avg * (x[i] - x_ref) # clockwise torque around (x_ref, y_ref)
88-
end
89-
end
90-
return c_te
91-
end
92-
93-
function solve_alpha!(cls, cds, c_tes, alphas, alpha_idxs, d_trailing_edge_angle, re, x_, y_, lower, upper, kite_speed, speed_of_sound)
59+
function solve_alpha!(cls, cds, cms, alphas, alpha_idxs, d_trailing_edge_angle, re, x_, y_, lower, upper, kite_speed, speed_of_sound)
9460
x = deepcopy(x_)
9561
y = deepcopy(y_)
9662
turn_trailing_edge!(d_trailing_edge_angle, x, y, lower, upper)
9763
Xfoil.set_coordinates(x, y)
9864
x, y = Xfoil.pane(npan=140)
99-
@show d_trailing_edge_angle
65+
@info d_trailing_edge_angle
10066
reinit = true
10167
for (alpha, alpha_idx) in zip(alphas, alpha_idxs)
10268
converged = false
10369
cl = 0.0
10470
cd = 0.0
10571
# Solve for the given angle of attack
106-
cl, cd, _, cm, converged = Xfoil.solve_alpha(alpha, re; iter=50, reinit=reinit, mach=kite_speed/speed_of_sound, xtrip=(0.05, 0.05)) # TODO: use 5% point
72+
cl, cd, _, cm, converged = Xfoil.solve_alpha(alpha, re; iter=50, reinit=reinit, mach=kite_speed/speed_of_sound, xtrip=(0.05, 0.05))
10773
reinit = false
10874
if converged
10975
_, cp = Xfoil.cpdump()
110-
c_te = calculate_constants(d_trailing_edge_angle, x, y, cp, lower, upper)
11176
cls[alpha_idx] = cl
11277
cds[alpha_idx] = cd
113-
c_tes[alpha_idx] = c_te
78+
cms[alpha_idx] = cm
11479
end
11580
end
11681
return nothing
@@ -119,16 +84,16 @@ function distributed_create_polars(foil_file, v_wind, middle_length, tip_length)
11984
function run_solve_alpha(alphas, d_trailing_edge_angle, re, x_, y_, lower, upper, kite_speed, speed_of_sound)
12085
cls = Float64[NaN for _ in alphas]
12186
cds = Float64[NaN for _ in alphas]
122-
c_tes = Float64[NaN for _ in alphas]
87+
cms = Float64[NaN for _ in alphas]
12388
neg_idxs = sort(findall(alphas .< 0.0), rev=true)
12489
neg_alphas = alphas[neg_idxs]
12590
pos_idxs = sort(findall(alphas .>= 0.0))
12691
pos_alphas = alphas[pos_idxs]
127-
solve_alpha!(cls, cds, c_tes, neg_alphas, neg_idxs, d_trailing_edge_angle,
92+
solve_alpha!(cls, cds, cms, neg_alphas, neg_idxs, d_trailing_edge_angle,
12893
re, x_, y_, lower, upper, kite_speed, speed_of_sound)
129-
solve_alpha!(cls, cds, c_tes, pos_alphas, pos_idxs, d_trailing_edge_angle,
94+
solve_alpha!(cls, cds, cms, pos_alphas, pos_idxs, d_trailing_edge_angle,
13095
re, x_, y_, lower, upper, kite_speed, speed_of_sound)
131-
return cls, cds, c_tes
96+
return cls, cds, cms
13297
end
13398
end
13499

@@ -139,13 +104,13 @@ function distributed_create_polars(foil_file, v_wind, middle_length, tip_length)
139104
min_upper_distance = Inf
140105
for (xi, yi) in zip(x, y)
141106
if yi < 0
142-
lower_distance = abs(xi - 0.75)
107+
lower_distance = abs(xi - x_turn)
143108
if lower_distance < min_lower_distance
144109
min_lower_distance = lower_distance
145110
lower_trailing_edge = yi
146111
end
147112
else
148-
upper_distance = abs(xi - 0.75)
113+
upper_distance = abs(xi - x_turn)
149114
if upper_distance < min_upper_distance
150115
min_upper_distance = upper_distance
151116
upper_trailing_edge = yi
@@ -163,26 +128,59 @@ function distributed_create_polars(foil_file, v_wind, middle_length, tip_length)
163128
return matrix[rows_to_keep, cols_to_keep]
164129
end
165130

166-
println("Creating polars")
167-
if !endswith(foil_file, ".dat")
168-
foil_file *= ".dat"
131+
function replace_nan!(matrix)
132+
rows, cols = size(matrix)
133+
distance = max(rows, cols)
134+
for i in 1:rows
135+
for j in 1:cols
136+
if isnan(matrix[i, j])
137+
neighbors = []
138+
for d in 1:distance
139+
found = false
140+
if i-d >= 1 && !isnan(matrix[i-d, j]);
141+
push!(neighbors, matrix[i-d, j])
142+
found = true
143+
end
144+
if i+d <= rows && !isnan(matrix[i+d, j])
145+
push!(neighbors, matrix[i+d, j])
146+
found = true
147+
end
148+
if j-d >= 1 && !isnan(matrix[i, j-d])
149+
push!(neighbors, matrix[i, j-d])
150+
found = true
151+
end
152+
if j+d <= cols && !isnan(matrix[i, j+d])
153+
push!(neighbors, matrix[i, j+d])
154+
found = true
155+
end
156+
if found; break; end
157+
end
158+
if !isempty(neighbors)
159+
matrix[i, j] = sum(neighbors) / length(neighbors)
160+
end
161+
end
162+
end
163+
end
164+
return nothing
169165
end
170-
polar_file = foil_file[1:end-4] * "_polar.bin"
171166

172-
# alphas = -90:1.0:90
173-
alphas = -1.0:1.0:1.0
174-
# d_trailing_edge_angles = -90:1.0:90
175-
d_trailing_edge_angles = -1.0:1.0:1.0
167+
@info "Creating polars"
168+
169+
alphas = -90:1.0:90
170+
# alphas = -1.0:1.0:1.0
171+
d_trailing_edge_angles = -90:1.0:90
172+
# d_trailing_edge_angles = -1.0:1.0:1.0
176173
cl_matrix = SharedArray{Float64}((length(alphas), length(d_trailing_edge_angles)), init = (a) -> fill!(a, NaN))
177174
cd_matrix = SharedArray{Float64}((length(alphas), length(d_trailing_edge_angles)), init = (a) -> fill!(a, NaN))
178-
c_te_matrix = SharedArray{Float64}((length(alphas), length(d_trailing_edge_angles)), init = (a) -> fill!(a, NaN))
175+
cm_matrix = SharedArray{Float64}((length(alphas), length(d_trailing_edge_angles)), init = (a) -> fill!(a, NaN))
179176

180177
kite_speed = v_wind
181178
speed_of_sound = 343
182-
reynolds_number = kite_speed * (middle_length + tip_length)/2 / 1.460e-5
179+
chord_length = area / width
180+
reynolds_number = kite_speed * chord_length / 1.460e-5 # wikipedia
183181

184182
# Read airfoil coordinates from a file.
185-
x, y = open(foil_file, "r") do f
183+
x, y = open(foil_path, "r") do f
186184
x = Float64[]
187185
y = Float64[]
188186
for line in eachline(f)
@@ -203,24 +201,37 @@ function distributed_create_polars(foil_file, v_wind, middle_length, tip_length)
203201

204202
try
205203
@sync @distributed for j in eachindex(d_trailing_edge_angles)
206-
cl_matrix[:, j], cd_matrix[:, j], c_te_matrix[:, j] = run_solve_alpha(alphas, d_trailing_edge_angles[j],
204+
cl_matrix[:, j], cd_matrix[:, j], cm_matrix[:, j] = run_solve_alpha(alphas, d_trailing_edge_angles[j],
207205
reynolds_number, x, y, lower, upper, kite_speed, speed_of_sound)
208206
end
209207
catch e
210-
println(e)
208+
rmprocs(procs)
209+
throw(e)
211210
finally
212-
println("Removing processes")
211+
@info "Removing processes"
213212
rmprocs(procs)
214213
end
215214

216-
println("cl_matrix")
217-
[println(cl_matrix[i, :]) for i in eachindex(alphas)]
215+
@info "cl_matrix" begin
216+
display(cl_matrix)
217+
end
218+
219+
replace_nan!(cl_matrix)
220+
replace_nan!(cd_matrix)
221+
replace_nan!(cm_matrix)
222+
223+
cl_interp_ = extrapolate(scale(interpolate(cl_matrix, BSpline(Linear())), alphas, d_trailing_edge_angles), NaN)
224+
cd_interp_ = extrapolate(scale(interpolate(cd_matrix, BSpline(Linear())), alphas, d_trailing_edge_angles), NaN)
225+
cm_interp_ = extrapolate(scale(interpolate(cm_matrix, BSpline(Linear())), alphas, d_trailing_edge_angles), NaN)
218226

219-
println("Relative trailing_edge height: ", upper - lower)
220-
println("Reynolds number for flying speed of $kite_speed is $reynolds_number")
227+
cl_interp = (α, β) -> cl_interp_(α, β)
228+
cd_interp = (α, β) -> cd_interp_(α, β)
229+
cm_interp = (α, β) -> cm_interp_(α, β)
221230

222-
serialize(polar_file, (alphas, d_trailing_edge_angles, Matrix(cl_matrix), Matrix(cd_matrix), Matrix(c_te_matrix)))
231+
@info "Relative trailing_edge height: $upper - $lower"
232+
@info "Reynolds number for flying speed of $kite_speed is $reynolds_number"
233+
234+
serialize(polar_path, (cl_interp, cd_interp, cm_interp))
223235
toc()
236+
return (cl_interp, cd_interp, cm_interp)
224237
end
225-
226-
distributed_create_polars("data/centre_line_profile_with_billow", 9.81, 2.0, 1.0)

0 commit comments

Comments
 (0)