@@ -815,10 +815,7 @@ function refine!(wing::AbstractWing; recompute_mapping=true, sort_sections=true)
815815 reuse_aero_data
816816 )
817817 elseif wing. spanwise_distribution == BILLOWING
818- refine_mesh_with_billowing! (
819- wing, LE, TE, aero_model, aero_data;
820- reuse_aero_data
821- )
818+ refine_mesh_with_billowing! (wing; reuse_aero_data)
822819 else
823820 throw (ArgumentError (" Unsupported spanwise panel distribution: $(wing. spanwise_distribution) " ))
824821 end
@@ -1118,14 +1115,18 @@ function refine_mesh_for_linear_cosine_distribution!(
11181115end
11191116
11201117"""
1121- refine_mesh_by_splitting_provided_sections!(wing::AbstractWing )
1118+ refine_mesh_by_splitting_provided_sections!(wing; reuse_aero_data, billowing_angle )
11221119
11231120Refine mesh by splitting provided sections into desired number of panels.
11241121
1125- Returns:
1126- Vector{Section}: Refined sections
1122+ When `billowing_angle > 0`, applies circular arc TE displacement to intermediate
1123+ sections within each rib pair (simulating fabric billowing between ribs).
11271124"""
1128- function refine_mesh_by_splitting_provided_sections! (wing:: AbstractWing ; reuse_aero_data:: Bool = false )
1125+ function refine_mesh_by_splitting_provided_sections! (
1126+ wing:: AbstractWing ;
1127+ reuse_aero_data:: Bool = false ,
1128+ billowing_angle:: Float64 = 0.0
1129+ )
11291130 n_sections_provided = length (wing. unrefined_sections)
11301131 n_panels_provided = n_sections_provided - 1
11311132 n_panels_desired = wing. n_panels
@@ -1197,6 +1198,7 @@ function refine_mesh_by_splitting_provided_sections!(wing::AbstractWing; reuse_a
11971198 ]
11981199
11991200 # Generate sections for this pair
1201+ start_idx = idx
12001202 idx = refine_mesh_for_linear_cosine_distribution! (
12011203 wing,
12021204 idx,
@@ -1209,6 +1211,61 @@ function refine_mesh_by_splitting_provided_sections!(wing::AbstractWing; reuse_a
12091211 endpoints= false ,
12101212 reuse_aero_data
12111213 )
1214+
1215+ # Apply billowing arc to the just-created sections
1216+ if billowing_angle > 0 && idx > start_idx
1217+ LE_1 = LE[left_section_index]
1218+ TE_1 = TE[left_section_index]
1219+ LE_2 = LE[left_section_index + 1 ]
1220+ TE_2 = TE[left_section_index + 1 ]
1221+
1222+ chord_1 = TE_1 - LE_1
1223+ chord_2 = TE_2 - LE_2
1224+ x_hat = normalize ((chord_1 + chord_2) / 2 )
1225+ y_hat = normalize (LE_1 - LE_2)
1226+ z_hat = cross (x_hat, y_hat)
1227+ z_norm = norm (z_hat)
1228+ if z_norm > 1e-10
1229+ z_hat = z_hat / z_norm
1230+
1231+ TE_mid = (TE_1 + TE_2) / 2
1232+ d = abs (dot (TE_1 - TE_2, y_hat))
1233+ span_len = norm (LE_1 - LE_2)
1234+ chord_len_1 = norm (chord_1)
1235+ chord_len_2 = norm (chord_2)
1236+
1237+ if d > 1e-12
1238+ R = (d / 2 ) / sin (billowing_angle)
1239+ h = (d / 2 ) / tan (billowing_angle)
1240+
1241+ for si in start_idx: (idx - 1 )
1242+ sec = wing. refined_sections[si]
1243+ t = dot (sec. LE_point - LE_2,
1244+ y_hat) / span_len
1245+
1246+ arc_y = - R * sin (
1247+ billowing_angle * (1 - 2 t))
1248+ arc_z = - h + R * cos (
1249+ billowing_angle * (1 - 2 t))
1250+ arc_TE = TE_mid +
1251+ arc_y * y_hat + arc_z * z_hat
1252+
1253+ chord_dir = arc_TE - sec. LE_point
1254+ chord_dir_len = norm (chord_dir)
1255+ if chord_dir_len > 1e-12
1256+ target_chord = (
1257+ t * chord_len_1 +
1258+ (1 - t) * chord_len_2)
1259+ sec. TE_point .= (
1260+ sec. LE_point +
1261+ (target_chord /
1262+ chord_dir_len) *
1263+ chord_dir)
1264+ end
1265+ end
1266+ end
1267+ end
1268+ end
12121269 end
12131270 end
12141271
@@ -1277,115 +1334,23 @@ function billowing_angle_from_percentage(percentage::Real)
12771334end
12781335
12791336"""
1280- refine_mesh_with_billowing!(wing, LE, TE, aero_model, aero_data ; reuse_aero_data)
1337+ refine_mesh_with_billowing!(wing; reuse_aero_data)
12811338
1282- Refine wing mesh using linear spacing, then apply circular arc billowing to TE positions .
1339+ Refine wing mesh using SPLIT_PROVIDED spacing with circular arc billowing.
12831340
12841341Between each pair of unrefined (rib) sections, the trailing edge follows a circular arc
12851342that bulges in the direction perpendicular to the chord and span (simulating fabric
12861343billowing between ribs on a ram-air kite). The leading edge stays linearly interpolated.
12871344
12881345The arc half-angle is `wing.billowing_angle` (0 = straight line, π/2 = semicircle).
1289- """
1290- function refine_mesh_with_billowing! (wing, LE, TE, aero_model, aero_data;
1291- reuse_aero_data:: Bool = false )
1292- n_sections = wing. n_panels + 1
12931346
1294- # Step 1: Do standard LINEAR refinement first
1295- refine_mesh_for_linear_cosine_distribution! (
1296- wing, 1 , LINEAR, n_sections, LE, TE, aero_model, aero_data;
1297- reuse_aero_data
1347+ Delegates to [`refine_mesh_by_splitting_provided_sections!`](@ref).
1348+ """
1349+ function refine_mesh_with_billowing! (wing; reuse_aero_data:: Bool = false )
1350+ refine_mesh_by_splitting_provided_sections! (
1351+ wing; reuse_aero_data,
1352+ billowing_angle= wing. billowing_angle
12981353 )
1299-
1300- angle = wing. billowing_angle
1301- if angle ≈ 0.0
1302- return nothing # No billowing needed
1303- end
1304-
1305- n_unrefined = length (wing. unrefined_sections)
1306-
1307- # Collect unrefined LE positions for rib detection
1308- unrefined_LEs = [s. LE_point for s in wing. unrefined_sections]
1309-
1310- # Iterate over each pair of adjacent unrefined sections (ribs)
1311- for rib_idx in 1 : (n_unrefined - 1 )
1312- LE_1 = wing. unrefined_sections[rib_idx]. LE_point
1313- TE_1 = wing. unrefined_sections[rib_idx]. TE_point
1314- LE_2 = wing. unrefined_sections[rib_idx + 1 ]. LE_point
1315- TE_2 = wing. unrefined_sections[rib_idx + 1 ]. TE_point
1316-
1317- # Build local coordinate frame
1318- chord_1 = TE_1 - LE_1
1319- chord_2 = TE_2 - LE_2
1320- x_hat = (chord_1 + chord_2) / 2
1321- x_hat = x_hat / max (norm (x_hat), 1e-12 )
1322-
1323- y_vec = LE_1 - LE_2 # spanwise: from section 2 toward section 1
1324- y_hat = y_vec / max (norm (y_vec), 1e-12 )
1325-
1326- z_hat = cross (x_hat, y_hat)
1327- z_hat = z_hat / max (norm (z_hat), 1e-12 )
1328-
1329- # Project unrefined TEs into the local yz plane
1330- TE_mid = (TE_1 + TE_2) / 2
1331- y1 = dot (TE_1 - TE_mid, y_hat)
1332- y2 = dot (TE_2 - TE_mid, y_hat)
1333- d = abs (y1 - y2) # chord length of the arc in yz plane
1334-
1335- if d < 1e-12
1336- continue # degenerate: both TEs at same spanwise position
1337- end
1338-
1339- # Circular arc parameters
1340- R = (d / 2 ) / sin (angle)
1341- h = (d / 2 ) / tan (angle) # center offset from midpoint along z
1342-
1343- # Spanwise extent of this rib pair (for checking membership)
1344- span_len = dot (LE_1 - LE_2, y_hat)
1345-
1346- # Rib chord lengths for interpolation
1347- chord_len_1 = norm (chord_1)
1348- chord_len_2 = norm (chord_2)
1349-
1350- # Displace TE of refined sections that fall between this rib pair
1351- for sec in wing. refined_sections
1352- # Skip sections at any unrefined rib position
1353- is_rib = any (norm (sec. LE_point - ule) < 0.01 for ule in unrefined_LEs)
1354- if is_rib
1355- continue
1356- end
1357-
1358- # Project refined section's LE onto the spanwise direction
1359- frac_vec = sec. LE_point - LE_2
1360- t = dot (frac_vec, y_hat) / span_len
1361-
1362- # Skip sections outside this rib pair
1363- if t < 0.01 || t > 0.99
1364- continue
1365- end
1366-
1367- # Arc parametrization: t=1 -> TE_1, t=0 -> TE_2
1368- # In local coords centered at TE midpoint:
1369- # y(t) = -R * sin(angle * (1 - 2t))
1370- # z(t) = -h + R * cos(angle * (1 - 2t))
1371- arc_y = - R * sin (angle * (1 - 2 t))
1372- arc_z = - h + R * cos (angle * (1 - 2 t))
1373-
1374- # Transform arc position back to global coords
1375- arc_TE = TE_mid + arc_y * y_hat + arc_z * z_hat
1376-
1377- # Preserve chord length: use the arc TE to define the chord
1378- # direction, but enforce the interpolated chord length
1379- chord_dir = arc_TE - sec. LE_point
1380- chord_dir_len = norm (chord_dir)
1381- if chord_dir_len > 1e-12
1382- target_chord = t * chord_len_1 + (1 - t) * chord_len_2
1383- sec. TE_point .= sec. LE_point + (target_chord / chord_dir_len) * chord_dir
1384- end
1385- end
1386- end
1387-
1388- return nothing
13891354end
13901355
13911356"""
0 commit comments