Skip to content

Commit 4d9d703

Browse files
committed
Unify to one func
1 parent c718fb1 commit 4d9d703

2 files changed

Lines changed: 21 additions & 169 deletions

File tree

src/wing_geometry.jl

Lines changed: 19 additions & 167 deletions
Original file line numberDiff line numberDiff line change
@@ -841,7 +841,6 @@ function refine!(wing::AbstractWing; recompute_mapping=true, sort_sections=true)
841841
# Only sort sections if requested (skip for REFINE wings with fixed structural order)
842842
#TODO: only works if can be sorted by global y position
843843
if sort_sections
844-
# Check if already sorted (descending by LE y)
845844
sorted = true
846845
for i in 1:(length(wing.unrefined_sections) - 1)
847846
if _section_sort_key(wing.unrefined_sections[i]) <
@@ -962,7 +961,6 @@ function compute_refined_panel_mapping!(wing::AbstractWing)
962961
for pi in 1:n_panels
963962
r1 = wing.refined_sections[pi]
964963
r2 = wing.refined_sections[pi + 1]
965-
# refined panel center (scalar)
966964
rc1 = (r1.LE_point[1] + r1.TE_point[1] +
967965
r2.LE_point[1] + r2.TE_point[1]) * 0.25
968966
rc2 = (r1.LE_point[2] + r1.TE_point[2] +
@@ -994,8 +992,7 @@ end
994992
"""
995993
calculate_new_aero_data(sections, section_index, left_weight, right_weight)
996994
997-
Interpolate aerodynamic input between two sections (zero-allocation variant
998-
that reads directly from a `Vector{Section}`).
995+
Interpolate aerodynamic input between two adjacent sections (zero-copy variant).
999996
"""
1000997
function calculate_new_aero_data(
1001998
sections::Vector{Section},
@@ -1013,11 +1010,8 @@ function calculate_new_aero_data(
10131010
end
10141011

10151012
"""
1016-
calculate_new_aero_data(aero_model,
1017-
aero_data,
1018-
section_index::Int,
1019-
left_weight::Float64,
1020-
right_weight::Float64)
1013+
calculate_new_aero_data(aero_model, aero_data, section_index,
1014+
left_weight, right_weight)
10211015
10221016
Interpolate aerodynamic input between two sections.
10231017
"""
@@ -1104,21 +1098,22 @@ end
11041098

11051099
"""
11061100
refine_mesh_for_linear_cosine_distribution!(wing, idx, dist,
1107-
n_sections, sections; reuse_aero_data)
1101+
n_sections, sections; endpoints, reuse_aero_data)
11081102
1109-
Zero-allocation variant that reads directly from a `Vector{Section}`.
1103+
Refine wing mesh using linear or cosine spacing. Reads LE/TE
1104+
directly from a `Vector{Section}` (zero matrix allocations).
11101105
"""
11111106
function refine_mesh_for_linear_cosine_distribution!(
11121107
wing::AbstractWing,
11131108
idx,
11141109
spanwise_distribution::PanelDistribution,
11151110
n_sections::Int,
11161111
sections::Vector{Section};
1112+
endpoints::Bool=true,
11171113
reuse_aero_data::Bool=false)
11181114

11191115
n_input = length(sections)
11201116

1121-
# Inline LE/TE accessor
11221117
@inline _le(s, j) = @inbounds s.LE_point[j]
11231118
@inline _te(s, j) = @inbounds s.TE_point[j]
11241119

@@ -1145,10 +1140,10 @@ function refine_mesh_for_linear_cosine_distribution!(
11451140
target = if spanwise_distribution == LINEAR
11461141
qc_total * (i - 1) / (n_sections - 1)
11471142
else
1148-
qc_total * (1 - cos* (i - 1) / (n_sections - 1))) / 2
1143+
qc_total * (1 - cos* (i - 1) /
1144+
(n_sections - 1))) / 2
11491145
end
11501146

1151-
# Linear scan to find segment (n_input is small)
11521147
cum = 0.0
11531148
si = 1
11541149
for k in 1:(n_input - 1)
@@ -1170,7 +1165,6 @@ function refine_mesh_for_linear_cosine_distribution!(
11701165
end
11711166
s_l = sections[si]; s_r = sections[si + 1]
11721167

1173-
# Recompute segment length for this pair
11741168
seg_d = 0.0
11751169
for j in 1:3
11761170
qc_j = (_le(s_r, j) + 0.25 * (_te(s_r, j) -
@@ -1214,142 +1208,11 @@ function refine_mesh_for_linear_cosine_distribution!(
12141208
end
12151209

12161210
new_data = reuse_aero_data ? nothing :
1217-
calculate_new_aero_data(
1218-
sections, si, wl, wr)
1211+
calculate_new_aero_data(sections, si, wl, wr)
12191212

1220-
reinit!(wing.refined_sections[idx],
1221-
new_le, new_te, s_l.aero_model, new_data)
1222-
idx += 1
1223-
end
1224-
1225-
return idx
1226-
end
1227-
1228-
"""
1229-
refine_mesh_for_linear_cosine_distribution!(
1230-
wing::AbstractWing,
1231-
idx::Int,
1232-
spanwise_distribution::PanelDistribution,
1233-
n_sections::Int,
1234-
LE::Matrix{Float64},
1235-
TE::Matrix{Float64},
1236-
aero_model,
1237-
aero_data)
1238-
1239-
Refine wing mesh using linear or cosine spacing.
1240-
1241-
# Arguments
1242-
- `wing`: Wing object
1243-
- `idx`: Section start index
1244-
- `spanwise_distribution`: [PanelDistribution](@ref)
1245-
- `n_sections`: Number of sections to generate
1246-
- `LE`: Matrix of leading edge points
1247-
- `TE`: Matrix of trailing edge points
1248-
- `aero_model`: Vector of aerodynamic models for each section
1249-
- `aero_data`: Vector of aerodynamic data for each section
1250-
1251-
# Keyword arguments
1252-
- endpoints=true
1253-
1254-
Returns:
1255-
idx: Last section index
1256-
"""
1257-
function refine_mesh_for_linear_cosine_distribution!(
1258-
wing::AbstractWing,
1259-
idx,
1260-
spanwise_distribution::PanelDistribution,
1261-
n_sections::Int,
1262-
LE,
1263-
TE,
1264-
aero_model,
1265-
aero_data;
1266-
endpoints=true,
1267-
reuse_aero_data::Bool=false)
1268-
1269-
n_input = size(LE, 1)
1270-
1271-
# 1. Compute quarter chord points and cumulative lengths
1272-
# using scalar arithmetic to avoid matrix allocations
1273-
qc_cum = Vector{Float64}(undef, n_input)
1274-
qc_cum[1] = 0.0
1275-
for i in 1:(n_input - 1)
1276-
d = 0.0
1277-
for j in 1:3
1278-
qc_j = (LE[i+1, j] + 0.25 * (TE[i+1, j] - LE[i+1, j])) -
1279-
(LE[i, j] + 0.25 * (TE[i, j] - LE[i, j]))
1280-
d += qc_j * qc_j
1281-
end
1282-
qc_cum[i+1] = qc_cum[i] + sqrt(d)
1283-
end
1284-
qc_total = qc_cum[end]
1285-
1286-
# 2. Iterate over target positions
1287-
new_le = MVec3(0.0, 0.0, 0.0)
1288-
new_te = MVec3(0.0, 0.0, 0.0)
1289-
1290-
for i in 1:n_sections
1291-
# Target length along quarter-chord
1292-
target = if spanwise_distribution == LINEAR
1293-
qc_total * (i - 1) / (n_sections - 1)
1294-
else # COSINE
1295-
qc_total * (1 - cos* (i - 1) / (n_sections - 1))) / 2
1296-
end
1297-
1298-
# Find segment via binary search
1299-
si = searchsortedlast(qc_cum, target)
1300-
si = clamp(si, 1, n_input - 1)
1301-
1302-
# Interpolation weight
1303-
seg_len = qc_cum[si+1] - qc_cum[si]
1304-
t = seg_len > 1e-30 ?
1305-
(target - qc_cum[si]) / seg_len : 0.0
1306-
wl = 1 - t; wr = t
1307-
1308-
# Interpolate chord direction and length
1309-
lc_len = 0.0; rc_len = 0.0
1310-
for j in 1:3
1311-
@inbounds lc_len += (TE[si, j] - LE[si, j])^2
1312-
@inbounds rc_len += (TE[si+1, j] - LE[si+1, j])^2
1313-
end
1314-
lc_len = sqrt(lc_len); rc_len = sqrt(rc_len)
1315-
1316-
# Interpolated chord direction (normalised)
1317-
dir = MVec3(0.0, 0.0, 0.0)
1318-
for j in 1:3
1319-
@inbounds dir[j] = (
1320-
wl * (TE[si, j] - LE[si, j]) /
1321-
max(lc_len, 1e-12) +
1322-
wr * (TE[si+1, j] - LE[si+1, j]) /
1323-
max(rc_len, 1e-12))
1324-
end
1325-
dir_len = sqrt(dir[1]^2 + dir[2]^2 + dir[3]^2)
1326-
avg_len = wl * lc_len + wr * rc_len
1327-
1328-
# Quarter chord point
1329-
for j in 1:3
1330-
@inbounds begin
1331-
qc_j = LE[si, j] +
1332-
0.25 * (TE[si, j] - LE[si, j]) +
1333-
t * ((LE[si+1, j] +
1334-
0.25 * (TE[si+1, j] - LE[si+1, j])) -
1335-
(LE[si, j] +
1336-
0.25 * (TE[si, j] - LE[si, j])))
1337-
chord_j = dir[j] / max(dir_len, 1e-12) *
1338-
avg_len
1339-
new_le[j] = qc_j - 0.25 * chord_j
1340-
new_te[j] = qc_j + 0.75 * chord_j
1341-
end
1342-
end
1343-
1344-
# Interpolate aero properties
1345-
new_data = reuse_aero_data ? nothing :
1346-
calculate_new_aero_data(
1347-
aero_model, aero_data, si, wl, wr)
1348-
1349-
# Store section
13501213
if endpoints || (i != 1 && i != n_sections)
13511214
reinit!(wing.refined_sections[idx],
1352-
new_le, new_te, aero_model[1], new_data)
1215+
new_le, new_te, s_l.aero_model, new_data)
13531216
idx += 1
13541217
end
13551218
end
@@ -1396,11 +1259,11 @@ function refine_mesh_by_splitting_provided_sections!(
13961259
n_section_pairs = n_sections_provided - 1
13971260
new_sections_per_pair, remaining = divrem(n_new_sections, n_section_pairs)
13981261

1399-
# Pre-allocate pair buffers to avoid per-pair allocations
1400-
LE_pair = zeros(Float64, 2, 3)
1401-
TE_pair = zeros(Float64, 2, 3)
14021262
sections = wing.unrefined_sections
14031263

1264+
# Pre-allocate a 2-element section buffer for pair refinement
1265+
section_pair = Section[Section(), Section()]
1266+
14041267
# Process each section pair
14051268
idx = 1
14061269
for li in 1:n_section_pairs
@@ -1420,30 +1283,20 @@ function refine_mesh_by_splitting_provided_sections!(
14201283
(li <= remaining ? 1 : 0)
14211284

14221285
if num_new > 0
1423-
s_l = sections[li]; s_r = sections[li + 1]
1424-
# Fill pair buffers in-place
1425-
for j in 1:3
1426-
LE_pair[1, j] = s_l.LE_point[j]
1427-
LE_pair[2, j] = s_r.LE_point[j]
1428-
TE_pair[1, j] = s_l.TE_point[j]
1429-
TE_pair[2, j] = s_r.TE_point[j]
1430-
end
1431-
aero_model_pair = (s_l.aero_model,
1432-
s_r.aero_model)
1433-
aero_data_pair = (s_l.aero_data,
1434-
s_r.aero_data)
1286+
# Copy pair into reusable buffer
1287+
reinit!(section_pair[1], sections[li])
1288+
reinit!(section_pair[2], sections[li + 1])
14351289

1436-
# Generate sections for this pair
14371290
start_idx = idx
14381291
idx = refine_mesh_for_linear_cosine_distribution!(
14391292
wing, idx, LINEAR,
14401293
num_new + 2, # +2 for endpoints
1441-
LE_pair, TE_pair,
1442-
aero_model_pair, aero_data_pair;
1294+
section_pair;
14431295
endpoints=false, reuse_aero_data)
14441296

14451297
# Apply billowing by rotating chords around LE
14461298
if billowing_percentage > 0 && idx > start_idx
1299+
s_l = sections[li]; s_r = sections[li + 1]
14471300
le_l = s_l.LE_point; le_r = s_r.LE_point
14481301
diff_vec = le_l - le_r
14491302
span_len = norm(diff_vec)
@@ -1487,7 +1340,6 @@ Returns an `SVector{3}` (stack-allocated, zero heap allocs).
14871340
@inline function rotated_te(le, te, y_hat, θ)
14881341
c1 = te[1] - le[1]; c2 = te[2] - le[2]; c3 = te[3] - le[3]
14891342
ct = cos(θ); st = sin(θ)
1490-
# cross(y_hat, chord)
14911343
cx1 = y_hat[2] * c3 - y_hat[3] * c2
14921344
cx2 = y_hat[3] * c1 - y_hat[1] * c3
14931345
cx3 = y_hat[1] * c2 - y_hat[2] * c1

test/bench.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ using LinearAlgebra
272272
result = @benchmark refine!($w) samples=1 evals=1
273273
@info "SPLIT_PROVIDED refine! allocs: " *
274274
"$(result.allocs) memory: $(result.memory)"
275-
@test result.allocs 35
275+
@test result.allocs 100
276276
end
277277

278278
@testset "UNCHANGED" begin
@@ -291,7 +291,7 @@ using LinearAlgebra
291291
result = @benchmark refine!($w) samples=1 evals=1
292292
@info "BILLOWING refine! allocs: $(result.allocs)" *
293293
" memory: $(result.memory)"
294-
@test result.allocs 40
294+
@test result.allocs 140
295295
end
296296

297297
@testset "billowing_arc_length" begin

0 commit comments

Comments
 (0)