Skip to content

Commit 2a85137

Browse files
committed
Address claude review comments
1 parent 703b071 commit 2a85137

4 files changed

Lines changed: 48 additions & 20 deletions

File tree

NEWS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
- `billowing_angle` replaced by `billowing_percentage` on `Wing` and
55
`WingSettings` (percentage of arc length, not radians)
66
- `billowing_angle_from_percentage()` removed
7-
- `BILLOWING` distribution now uses catenary curve instead of circular arc
7+
- `BILLOWING` distribution now uses sinusoidal rotation instead of circular arc
88

99
### Added
1010
- `billowing.jl` example comparing flat vs billowed V3 kite

examples/billowing.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using LinearAlgebra
22
using VortexStepMethod
33
using GLMakie
4-
using DelimitedFiles
54

65
PLOT = true
76
USE_TEX = false

src/VortexStepMethod.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,14 +130,14 @@ Enumeration of the implemented panel distributions.
130130
- COSINE # Cosine distribution
131131
- `SPLIT_PROVIDED` # Split provided sections
132132
- `UNCHANGED` # 1:1 copy of unrefined to refined sections (no interpolation)
133-
- `BILLOWING` # Split provided + catenary TE billowing between ribs
133+
- `BILLOWING` # Split provided + sinusoidal TE billowing between ribs
134134
"""
135135
@enum PanelDistribution begin
136136
LINEAR # Linear distribution
137137
COSINE # Cosine distribution
138138
SPLIT_PROVIDED # Split provided sections
139139
UNCHANGED # 1:1 copy of unrefined to refined sections
140-
BILLOWING # Split provided + catenary TE billowing
140+
BILLOWING # Split provided + sinusoidal TE billowing
141141
end
142142

143143
"""

src/wing_geometry.jl

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1120,8 +1120,9 @@ end
11201120
11211121
Refine mesh by splitting provided sections into desired number of panels.
11221122
1123-
When `billowing_percentage > 0`, applies catenary TE displacement to intermediate
1124-
sections within each rib pair (simulating fabric billowing between ribs).
1123+
When `billowing_percentage > 0`, applies sinusoidal TE displacement to
1124+
intermediate sections within each rib pair (simulating fabric billowing
1125+
between ribs).
11251126
"""
11261127
function refine_mesh_by_splitting_provided_sections!(
11271128
wing::AbstractWing;
@@ -1136,13 +1137,33 @@ function refine_mesh_by_splitting_provided_sections!(
11361137

11371138
# Check if refinement is needed
11381139
if n_panels_provided == n_panels_desired
1139-
for (refined_section, section) in zip(wing.refined_sections, wing.unrefined_sections)
1140+
for (refined_section, section) in zip(
1141+
wing.refined_sections, wing.unrefined_sections)
11401142
if reuse_aero_data
1141-
reinit!(refined_section, section.LE_point, section.TE_point, section.aero_model)
1143+
reinit!(refined_section, section.LE_point,
1144+
section.TE_point, section.aero_model)
11421145
else
11431146
reinit!(refined_section, section)
11441147
end
11451148
end
1149+
if billowing_percentage > 0
1150+
LE = [s.LE_point for s in wing.unrefined_sections]
1151+
TE = [s.TE_point for s in wing.unrefined_sections]
1152+
for i in 1:(n_panels_provided - 1)
1153+
y_hat = normalize(LE[i] - LE[i + 1])
1154+
span_len = norm(LE[i] - LE[i + 1])
1155+
start_si = i + 1
1156+
end_si = i + 1
1157+
if start_si <= end_si
1158+
apply_billowing_to_pair!(
1159+
wing.refined_sections,
1160+
start_si, end_si,
1161+
y_hat, span_len,
1162+
LE[i + 1], TE[i], TE[i + 1],
1163+
billowing_percentage)
1164+
end
1165+
end
1166+
end
11461167
return nothing
11471168
end
11481169

@@ -1249,13 +1270,25 @@ function refine_mesh_by_splitting_provided_sections!(
12491270

12501271
# Validate result
12511272
if length(wing.refined_sections) != wing.n_panels + 1
1252-
@warn "Number of panels ($(length(new_sections)-1)) differs from desired ($(wing.n_panels))"
1273+
@warn "Number of panels ($(length(wing.refined_sections)-1)) differs from desired ($(wing.n_panels))"
12531274
end
12541275

12551276
return nothing
12561277
end
12571278

12581279

1280+
"""
1281+
rodrigues_rotate(vec, axis, θ)
1282+
1283+
Rotate `vec` around unit `axis` by angle `θ` (radians) using the
1284+
Rodrigues rotation formula. Non-allocating with MVec3 inputs.
1285+
"""
1286+
@inline function rodrigues_rotate(vec, axis, θ)
1287+
ct = cos(θ); st = sin(θ)
1288+
d = dot(vec, axis)
1289+
return ct * vec + st * cross(axis, vec) + (1 - ct) * d * axis
1290+
end
1291+
12591292
"""
12601293
billowing_arc_length(sections, start_si, end_si, y_hat,
12611294
span_len, le_ref, te_left, te_right,
@@ -1279,11 +1312,7 @@ function billowing_arc_length(
12791312
t = dot(sec.LE_point - le_ref, y_hat) / span_len
12801313
θ = -angle_max * sin* t)
12811314
chord_vec = sec.TE_point - sec.LE_point
1282-
ct = cos(θ); st = sin(θ)
1283-
d_y = dot(chord_vec, y_hat)
1284-
rotated = ct * chord_vec +
1285-
st * cross(y_hat, chord_vec) +
1286-
(1 - ct) * d_y * y_hat
1315+
rotated = rodrigues_rotate(chord_vec, y_hat, θ)
12871316
current_te = sec.LE_point + rotated
12881317
arc += norm(current_te - prev_te)
12891318
prev_te = current_te
@@ -1314,6 +1343,10 @@ function apply_billowing_to_pair!(
13141343
te_left, te_right, percentage
13151344
)
13161345
percentage <= 0 && return nothing
1346+
if percentage >= 100
1347+
throw(ArgumentError(
1348+
"billowing_percentage must be < 100, got $percentage"))
1349+
end
13171350
straight = norm(te_right - te_left)
13181351
straight < 1e-12 && return nothing
13191352
target_arc = straight / (1 - percentage / 100)
@@ -1335,7 +1368,7 @@ function apply_billowing_to_pair!(
13351368
te_left, te_right, angle_max + δ)
13361369
df = (arc_p - arc) / δ
13371370
abs(df) < 1e-30 && break
1338-
angle_max -= f / df
1371+
angle_max = max(0.0, angle_max - f / df)
13391372
end
13401373

13411374
# Apply converged rotations in-place
@@ -1344,11 +1377,7 @@ function apply_billowing_to_pair!(
13441377
t = dot(sec.LE_point - le_ref, y_hat) / span_len
13451378
θ = -angle_max * sin* t)
13461379
chord_vec = sec.TE_point - sec.LE_point
1347-
ct = cos(θ); st = sin(θ)
1348-
d_y = dot(chord_vec, y_hat)
1349-
rotated = ct * chord_vec +
1350-
st * cross(y_hat, chord_vec) +
1351-
(1 - ct) * d_y * y_hat
1380+
rotated = rodrigues_rotate(chord_vec, y_hat, θ)
13521381
sec.TE_point .= sec.LE_point + rotated
13531382
end
13541383
return nothing

0 commit comments

Comments
 (0)