Skip to content

Commit cb43571

Browse files
authored
Remove interpolation allocation (#67)
* make example bench more proper * working low allocation ram kite * fix tests * remove global * add comment * change back to old bench * change center name * remove second parameter syntax
1 parent c7a9df9 commit cb43571

File tree

10 files changed

+181
-155
lines changed

10 files changed

+181
-155
lines changed

examples/ram_air_kite.jl

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,6 @@ VSM = Solver(
2020
aerodynamic_model_type=:VSM,
2121
is_with_artificial_damping=false
2222
)
23-
VSM_with_stall_correction = Solver(
24-
aerodynamic_model_type=:VSM,
25-
is_with_artificial_damping=true
26-
)
2723

2824
# Setting velocity conditions
2925
v_a = 15.0

scripts/polars.jl

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using Distributed, Timers, Serialization, SharedArrays
1+
using Distributed, Timers, Serialization, SharedArrays, StaticArrays
22
using Interpolations
33
using Xfoil
44
using ControlPlots
@@ -204,6 +204,10 @@ try
204204
cl_matrix[:, j], cd_matrix[:, j], cm_matrix[:, j] = run_solve_alpha(alphas, d_trailing_edge_angles[j],
205205
reynolds_number, x, y, lower, upper, kite_speed, SPEED_OF_SOUND, x_turn)
206206
end
207+
cl_matrix = Matrix{Float64}(cl_matrix)
208+
cd_matrix = Matrix{Float64}(cd_matrix)
209+
cm_matrix = Matrix{Float64}(cm_matrix)
210+
207211
display(cl_matrix)
208212

209213
function plot_values(alphas, d_trailing_edge_angles, matrix, interp, name)
@@ -213,7 +217,8 @@ try
213217
X_data = collect(d_trailing_edge_angles) .+ zeros(length(alphas))'
214218
Y_data = collect(alphas)' .+ zeros(length(d_trailing_edge_angles))
215219

216-
interp_matrix = similar(matrix)
220+
matrix = Matrix{Float64}(matrix)
221+
interp_matrix = zeros(size(matrix)...)
217222
int_alphas, int_d_trailing_edge_angles = alphas .+ deg2rad(0.5), d_trailing_edge_angles .+ deg2rad(0.5)
218223
interp_matrix .= [interp(alpha, d_trailing_edge_angle) for alpha in int_alphas, d_trailing_edge_angle in int_d_trailing_edge_angles]
219224
X_int = collect(int_d_trailing_edge_angles) .+ zeros(length(int_alphas))'
@@ -241,7 +246,7 @@ try
241246
@info "Relative trailing_edge height: $(upper - lower)"
242247
@info "Reynolds number for flying speed of $kite_speed is $reynolds_number"
243248

244-
serialize(polar_path, (cl_interp, cd_interp, cm_interp))
249+
serialize(polar_path, (alphas, d_trailing_edge_angles, cl_matrix, cd_matrix, cm_matrix))
245250

246251
catch e
247252
@info "Removing processes"

src/VortexStepMethod.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ using ControlPlots
1010
using Measures
1111
using LaTeXStrings
1212
using NonlinearSolve
13-
using Interpolations: linear_interpolation, Line, Extrapolation
13+
using Interpolations
14+
using Interpolations: linear_interpolation, Line, Extrapolation, FilledExtrapolation
1415
using Serialization
1516
using SharedArrays
1617

src/kite_geometry.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,15 +241,15 @@ mutable struct KiteWing <: AbstractWing
241241
end
242242

243243
@info "Loding polars and kite info from $polar_path and $info_path"
244-
(cl_interp, cd_interp, cm_interp) = deserialize(polar_path)
244+
(alpha_range, beta_range, cl_matrix::Matrix, cd_matrix::Matrix, cm_matrix::Matrix) = deserialize(polar_path)
245245

246246
(center_of_mass, inertia_tensor, circle_center_z, radius, gamma_tip,
247247
le_interp, te_interp, area_interp) = deserialize(info_path)
248248

249249
# Create sections
250250
sections = Section[]
251251
for gamma in range(-gamma_tip, gamma_tip, n_sections)
252-
aero_input = (:interpolations, (cl_interp, cd_interp, cm_interp))
252+
aero_input = (:polar_data, (alpha_range, beta_range, cl_matrix, cd_matrix, cm_matrix))
253253
LE_point = [0.0, 0.0, circle_center_z] .+ [le_interp(gamma), sin(gamma) * radius, cos(gamma) * radius]
254254
if !isapprox(alpha, 0.0)
255255
local_y_vec = [0.0, sin(-gamma), cos(gamma)] × [1.0, 0.0, 0.0]

src/panel.jl

Lines changed: 71 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
using LinearAlgebra
22

3+
# static types for interpolations
4+
const I1 = Interpolations.FilledExtrapolation{Float64, 1, Interpolations.GriddedInterpolation{Float64, 1, Vector{Float64}, Interpolations.Gridded{Interpolations.Linear{Interpolations.Throw{Interpolations.OnGrid}}}, Tuple{Vector{Float64}}}, Interpolations.Gridded{Interpolations.Linear{Interpolations.Throw{Interpolations.OnGrid}}}, Float64}
5+
const I2 = Interpolations.FilledExtrapolation{Float64, 2, Interpolations.GriddedInterpolation{Float64, 2, Matrix{Float64}, Interpolations.Gridded{Interpolations.Linear{Interpolations.Throw{Interpolations.OnGrid}}}, Tuple{Vector{Float64}, Vector{Float64}}}, Interpolations.Gridded{Interpolations.Linear{Interpolations.Throw{Interpolations.OnGrid}}}, Float64}
6+
37
"""
48
Panel
59
@@ -36,9 +40,9 @@ mutable struct Panel
3640
cl_coefficients::Vector{Float64}
3741
cd_coefficients::Vector{Float64}
3842
cm_coefficients::Vector{Float64}
39-
cl_interp::Function
40-
cd_interp::Function
41-
cm_interp::Function
43+
cl_interp::Union{Nothing, I1, I2}
44+
cd_interp::Union{Nothing, I1, I2}
45+
cm_interp::Union{Nothing, I1, I2}
4246
aero_center::MVec3
4347
control_point::MVec3
4448
bound_point_1::MVec3
@@ -82,45 +86,65 @@ mutable struct Panel
8286

8387
# Initialize aerodynamic properties
8488
cl_coeffs, cd_coeffs, cm_coeffs = zeros(3), zeros(3), zeros(3)
85-
cl_interp, cd_interp, cm_interp =::Float64)->0.0, (α::Float64)->0.0, (α::Float64)->0.0
8689

90+
# Calculate width
91+
width = norm(bound_point_2 - bound_point_1)
92+
93+
# Initialize filaments
94+
filaments = [
95+
BoundFilament(bound_point_2, bound_point_1),
96+
BoundFilament(bound_point_1, TE_point_1),
97+
BoundFilament(TE_point_2, bound_point_2)
98+
]
99+
100+
cl_interp, cd_interp, cm_interp = nothing, nothing, nothing
101+
87102
if aero_model === :lei_airfoil_breukels
88103
cl_coeffs, cd_coeffs, cm_coeffs = compute_lei_coefficients(section_1, section_2)
104+
89105
elseif aero_model === :polar_data
90106
aero_1 = section_1.aero_input[2]
91107
aero_2 = section_2.aero_input[2]
92-
if size(aero_1) != size(aero_2)
108+
if !all(size.(aero_1) .== size.(aero_2))
93109
throw(ArgumentError("Polar data must have same shape"))
94110
end
95-
polar_data = (aero_1 + aero_2) / 2
96-
cl_interp_ = linear_interpolation(polar_data[:,1], polar_data[:,2]; extrapolation_bc=NaN)
97-
cd_interp_ = linear_interpolation(polar_data[:,1], polar_data[:,3]; extrapolation_bc=NaN)
98-
cm_interp_ = linear_interpolation(polar_data[:,1], polar_data[:,4]; extrapolation_bc=NaN)
99-
cl_interp =::Float64) -> cl_interp_(α)
100-
cd_interp =::Float64) -> cd_interp_(α)
101-
cm_interp =::Float64) -> cm_interp_(α)
102-
elseif aero_model === :interpolations
103-
cl_left, cd_left, cm_left = section_1.aero_input[2]
104-
cl_right, cd_right, cm_right = section_2.aero_input[2]
105-
cl_interp = cl_left === cl_right ?::Float64) -> cl_left(α, 0.0) :
106-
::Float64) -> 0.5cl_left(α, 0.0) + 0.5cl_right(α, 0.0) # TODO: add trailing edge deflection
107-
cd_interp = cd_left === cd_right ?::Float64) -> cd_left(α, 0.0) :
108-
::Float64) -> 0.5cd_left(α, 0.0) + 0.5cd_right(α, 0.0)
109-
cm_interp = cm_left === cm_right ?::Float64) -> cm_left(α, 0.0) :
110-
::Float64) -> 0.5cm_left(α, 0.0) + 0.5cm_right(α, 0.0)
111+
112+
if length(aero_1) == 4
113+
!all(isapprox.(aero_1[1], aero_2[1])) && @error "Make sure you use the same alpha range for all your interpolations."
114+
115+
polar_data = (
116+
Vector{Float64}((aero_1[2] + aero_2[2]) / 2),
117+
Vector{Float64}((aero_1[3] + aero_2[3]) / 2),
118+
Vector{Float64}((aero_1[4] + aero_2[4]) / 2)
119+
)
120+
alphas = Vector{Float64}(aero_1[1])
121+
122+
cl_interp = linear_interpolation(alphas, polar_data[1]; extrapolation_bc=NaN)
123+
cd_interp = linear_interpolation(alphas, polar_data[2]; extrapolation_bc=NaN)
124+
cm_interp = linear_interpolation(alphas, polar_data[3]; extrapolation_bc=NaN)
125+
126+
elseif length(aero_1) == 5
127+
!all(isapprox.(aero_1[1], aero_2[1])) && @error "Make sure you use the same alpha range for all your interpolations."
128+
!all(isapprox.(aero_1[2], aero_2[2])) && @error "Make sure you use the same beta range for all your interpolations."
129+
130+
polar_data = (
131+
Matrix{Float64}((aero_1[3] + aero_2[3]) / 2),
132+
Matrix{Float64}((aero_1[4] + aero_2[4]) / 2),
133+
Matrix{Float64}((aero_1[5] + aero_2[5]) / 2)
134+
)
135+
alphas = Vector{Float64}(aero_1[1])
136+
betas = Vector{Float64}(aero_1[2])
137+
138+
cl_interp = linear_interpolation((alphas, betas), polar_data[1]; extrapolation_bc=NaN)
139+
cd_interp = linear_interpolation((alphas, betas), polar_data[2]; extrapolation_bc=NaN)
140+
cm_interp = linear_interpolation((alphas, betas), polar_data[3]; extrapolation_bc=NaN)
141+
else
142+
throw(ArgumentError("Polar data in wrong format: $aero_1"))
143+
end
144+
111145
elseif !(aero_model === :inviscid)
112146
throw(ArgumentError("Unsupported aero model: $aero_model"))
113147
end
114-
115-
# Calculate width
116-
width = norm(bound_point_2 - bound_point_1)
117-
118-
# Initialize filaments
119-
filaments = [
120-
BoundFilament(bound_point_2, bound_point_1),
121-
BoundFilament(bound_point_1, TE_point_1),
122-
BoundFilament(TE_point_2, bound_point_2)
123-
]
124148

125149
new(
126150
TE_point_1, LE_point_1, TE_point_2, LE_point_2,
@@ -262,8 +286,14 @@ function calculate_cl(panel::Panel, alpha::Float64)::Float64
262286
end
263287
elseif panel.aero_model === :inviscid
264288
cl = 2π * alpha
265-
elseif panel.aero_model === :polar_data || panel.aero_model === :interpolations
266-
cl = panel.cl_interp(alpha)::Float64
289+
elseif panel.aero_model === :polar_data
290+
if isa(panel.cl_interp, I1)
291+
cl = panel.cl_interp(alpha)::Float64
292+
elseif isa(panel.cl_interp, I2)
293+
cl = panel.cl_interp(alpha, 0.0)::Float64
294+
else
295+
throw(ArgumentError("cl_interp is $(panel.cl_interp)"))
296+
end
267297
else
268298
throw(ArgumentError("Unsupported aero model: $(panel.aero_model)"))
269299
end
@@ -284,9 +314,14 @@ function calculate_cd_cm(panel::Panel, alpha::Float64)
284314
if abs(alpha) >/9) # Outside ±20 degrees
285315
cd = 2 * sin(alpha)^3
286316
end
287-
elseif panel.aero_model === :polar_data || panel.aero_model === :interpolations
288-
cd = panel.cd_interp(alpha)::Float64
289-
cm = panel.cm_interp(alpha)::Float64
317+
elseif panel.aero_model === :polar_data
318+
if isa(panel.cd_interp, I1)
319+
cd = panel.cd_interp(alpha)::Float64
320+
cm = panel.cm_interp(alpha)::Float64
321+
elseif isa(panel.cd_interp, I2)
322+
cd = panel.cd_interp(alpha, 0.0)::Float64
323+
cm = panel.cm_interp(alpha, 0.0)::Float64
324+
end
290325
elseif !(panel.aero_model === :inviscid)
291326
throw(ArgumentError("Unsupported aero model: $(panel.aero_model)"))
292327
end

src/solver.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ function solve(solver::Solver, body_aero::BodyAerodynamics, gamma_distribution=n
147147
)
148148
# Try again with reduced relaxation factor if not converged
149149
if !converged && relaxation_factor > 1e-3
150-
@warn "Running again with half the relaxation_factor = $(relaxation_factor/2)"
150+
log && @warn "Running again with half the relaxation_factor = $(relaxation_factor/2)"
151151
converged, gamma_new, alpha_array, v_a_array = gamma_loop(
152152
solver,
153153
body_aero,
@@ -158,7 +158,8 @@ function solve(solver::Solver, body_aero::BodyAerodynamics, gamma_distribution=n
158158
y_airf_array,
159159
z_airf_array,
160160
panels,
161-
relaxation_factor/2
161+
relaxation_factor/2;
162+
log
162163
)
163164
end
164165

src/wing_geometry.jl

Lines changed: 32 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ Add a new section to the wing.
6868
- aero_input: Can be:
6969
- :inviscid
7070
- :`lei_airfoil_breukels`
71-
- (:interpolations, (`cl_interp`, `cd_interp`, `cm_interp`))
71+
- (:polar_data, (`alpha_range`, `cl_vector`, `cd_vector`, `cm_vector`))
72+
- (:polar_data, (`alpha_range`, `beta_range`, `cl_matrix`, `cd_matrix`, `cm_matrix`))
7273
"""
7374
function add_section!(wing::Wing, LE_point::Vector{Float64},
7475
TE_point::Vector{Float64}, aero_input)
@@ -157,34 +158,6 @@ function refine_aerodynamic_mesh(wing::AbstractWing)
157158
end
158159
end
159160

160-
"""
161-
interpolate_to_common_alpha(alpha_common::Vector{Float64},
162-
alpha_orig::Vector{Float64},
163-
CL_orig::Vector{Float64},
164-
CD_orig::Vector{Float64},
165-
CM_orig::Vector{Float64})
166-
167-
Interpolate aerodynamic coefficients to a common alpha range.
168-
"""
169-
function interpolate_to_common_alpha(alpha_common,
170-
alpha_orig,
171-
CL_orig,
172-
CD_orig,
173-
CM_orig)
174-
175-
# Create interpolation objects
176-
itp_CL = linear_interpolation(alpha_orig, CL_orig)
177-
itp_CD = linear_interpolation(alpha_orig, CD_orig)
178-
itp_CM = linear_interpolation(alpha_orig, CM_orig)
179-
180-
# Evaluate at common alpha points
181-
CL_common = itp_CL.(alpha_common)
182-
CD_common = itp_CD.(alpha_common)
183-
CM_common = itp_CM.(alpha_common)
184-
185-
return CL_common, CD_common, CM_common
186-
end
187-
188161
"""
189162
calculate_new_aero_input(aero_input,
190163
section_index::Int,
@@ -212,46 +185,38 @@ function calculate_new_aero_input(aero_input,
212185
polar_right = aero_input[section_index + 1][2]
213186

214187
# Unpack polar data
215-
@views begin
216-
alpha_left, CL_left, CD_left, CM_left = (
217-
polar_left[:, i] for i in 1:4
218-
)
219-
alpha_right, CL_right, CD_right, CM_right = (
220-
polar_right[:, i] for i in 1:4
221-
)
222-
end
223-
224-
# Create common alpha array
225-
alpha_common = sort(unique(vcat(alpha_left, alpha_right)))
226-
227-
# Interpolate both polars
228-
CL_left_common, CD_left_common, CM_left_common = interpolate_to_common_alpha(
229-
alpha_common, alpha_left, CL_left, CD_left, CM_left
230-
)
231-
CL_right_common, CD_right_common, CM_right_common = interpolate_to_common_alpha(
232-
alpha_common, alpha_right, CL_right, CD_right, CM_right
233-
)
234-
235-
# Weighted interpolation
236-
CL_interp = CL_left_common .* left_weight .+ CL_right_common .* right_weight
237-
CD_interp = CD_left_common .* left_weight .+ CD_right_common .* right_weight
238-
CM_interp = CM_left_common .* left_weight .+ CM_right_common .* right_weight
239-
240-
return (:polar_data, hcat(alpha_common, CD_interp, CL_interp, CM_interp))
188+
if length(polar_left) == 4
189+
alpha_left, CL_left, CD_left, CM_left = polar_left
190+
alpha_right, CL_right, CD_right, CM_right = polar_right
241191

242-
elseif model_type === :interpolations
243-
cl_left, cd_left, cm_left = aero_input[section_index][2]
244-
cl_right, cd_right, cm_right = aero_input[section_index + 1][2]
245-
246-
cl_interp = cl_left === cl_right ? (α, β) -> cl_left[α, β] :
247-
(α, β) -> left_weight * cl_left[α, β] + right_weight * cl_right[α, β]
248-
cd_interp = cd_left === cd_right ? (α, β) -> cd_left[α, β] :
249-
(α, β) -> left_weight * cd_left[α, β] + right_weight * cd_right[α, β]
250-
cm_interp = cm_left === cm_right ? (α, β) -> cm_left[α, β] :
251-
(α, β) -> left_weight * cm_left[α, β] + right_weight * cm_right[α, β]
192+
# Create common alpha array
193+
!all(isapprox.(alpha_left, alpha_right)) && @error "Make sure you use the same alpha range for all your interpolations."
194+
!isa(CL_right, AbstractVector) && @error "Provide polar data in the correct format: (alpha, cl, cd, cm)"
195+
196+
# Weighted interpolation
197+
CL_data = CL_left .* left_weight .+ CL_right .* right_weight
198+
CD_data = CD_left .* left_weight .+ CD_right .* right_weight
199+
CM_data = CM_left .* left_weight .+ CM_right .* right_weight
200+
201+
return (:polar_data, (alpha_left, CL_data, CD_data, CM_data))
202+
203+
elseif length(polar_left) == 5
204+
alpha_left, beta_left, CL_left, CD_left, CM_left = polar_left
205+
alpha_right, beta_right, CL_right, CD_right, CM_right = polar_right
206+
207+
# Create common alpha array
208+
!all(isapprox.(alpha_left, alpha_right)) && @error "Make sure you use the same alpha range for all your interpolations."
209+
!all(isapprox.(beta_left, beta_right)) && @error "Make sure you use the same alpha range for all your interpolations."
210+
!isa(CL_right, AbstractMatrix) && @error "Provide polar data in the correct format: (alpha, beta, cl, cd, cm)"
211+
212+
# Weighted interpolation
213+
CL_data = CL_left .* left_weight .+ CL_right .* right_weight
214+
CD_data = CD_left .* left_weight .+ CD_right .* right_weight
215+
CM_data = CM_left .* left_weight .+ CM_right .* right_weight
216+
217+
return (:polar_data, (alpha_left, beta_left, CL_data, CD_data, CM_data))
218+
end
252219

253-
return (:interpolations, (cl_interp, cd_interp, cm_interp))
254-
255220
elseif model_type === :lei_airfoil_breukels
256221
tube_diameter_left = aero_input[section_index][2][1]
257222
tube_diameter_right = aero_input[section_index + 1][2][1]

0 commit comments

Comments
 (0)