Skip to content

Commit 1d76212

Browse files
1-Bort-1claude
andcommitted
Name linearize's locals and share the two-wing test setup
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent 580cd2f commit 1d76212

3 files changed

Lines changed: 52 additions & 45 deletions

File tree

src/body_aerodynamics.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -260,13 +260,13 @@ which run over the unrefined sections of all wings in order; `nothing` leaves th
260260
unchanged. Call [`reinit!`](@ref) afterwards to update the panels.
261261
"""
262262
function unrefined_deform!(body_aero::BodyAerodynamics, theta_angles, delta_angles)
263-
first_section = 1
263+
section_offset = 0
264264
for wing in body_aero.wings
265-
wing_sections = first_section:first_section + wing.n_unrefined_sections - 1
265+
section_idxs = section_offset .+ (1:wing.n_unrefined_sections)
266266
unrefined_deform!(wing,
267-
isnothing(theta_angles) ? nothing : view(theta_angles, wing_sections),
268-
isnothing(delta_angles) ? nothing : view(delta_angles, wing_sections))
269-
first_section += wing.n_unrefined_sections
267+
isnothing(theta_angles) ? nothing : view(theta_angles, section_idxs),
268+
isnothing(delta_angles) ? nothing : view(delta_angles, section_idxs))
269+
section_offset += wing.n_unrefined_sections
270270
end
271271
return nothing
272272
end

src/solver.jl

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1177,16 +1177,19 @@ function _wing_with_eltype(wing::Wing{P, Float64}, ::Type{TD}) where {P, TD}
11771177
wing.spanwise_distribution,
11781178
PanelProperties{P, TD}(),
11791179
MVector{3, TD}(wing.spanwise_direction),
1180-
Section{TD}[_section_with_eltype(s, TD) for s in wing.unrefined_sections],
1181-
Section{TD}[_section_with_eltype(s, TD) for s in wing.refined_sections],
1180+
Section{TD}[_section_with_eltype(section, TD)
1181+
for section in wing.unrefined_sections],
1182+
Section{TD}[_section_with_eltype(section, TD)
1183+
for section in wing.refined_sections],
11821184
wing.remove_nan,
11831185
wing.use_prior_polar,
11841186
wing.billowing_percentage,
11851187
TD(wing.crease_frac),
11861188
copy(wing.refined_panel_mapping),
11871189
copy(wing.refined_section_left_idx),
11881190
Vector{TD}(wing.refined_section_weight),
1189-
Section{TD}[_section_with_eltype(s, TD) for s in wing.non_deformed_sections],
1191+
Section{TD}[_section_with_eltype(section, TD)
1192+
for section in wing.non_deformed_sections],
11901193
Vector{TD}(wing.theta_dist),
11911194
Vector{TD}(wing.delta_dist),
11921195
TD(wing.mass),
@@ -1261,7 +1264,7 @@ Returns `(jac, results, converged)` where `results` is `(F, M, moment_unrefined_
12611264
or the corresponding coefficients when `aero_coeffs=true` — and `converged` is `false` (with a
12621265
warning) if any internal solve missed the solver's tolerances.
12631266
"""
1264-
function linearize(solver::Solver{P, U}, body_aero::BodyAerodynamics, y::Vector{T};
1267+
function linearize(solver::Solver{<:Any, U}, body_aero::BodyAerodynamics, y::Vector{T};
12651268
theta_idxs=1:4,
12661269
delta_idxs=nothing,
12671270
va_idxs=nothing,
@@ -1270,11 +1273,12 @@ function linearize(solver::Solver{P, U}, body_aero::BodyAerodynamics, y::Vector{
12701273
backend = AutoForwardDiff(),
12711274
fd_absstep::Float64=1e-8,
12721275
fd_relstep::Float64=1e-8,
1273-
kwargs...) where {P, U, T}
1276+
kwargs...) where {U, T}
12741277

12751278
for (name, idxs) in (("theta_idxs", theta_idxs), ("delta_idxs", delta_idxs))
12761279
isnothing(idxs) || length(idxs) == U || throw(ArgumentError(
1277-
"Length of $name ($(length(idxs))) must match number of unrefined sections ($U)"))
1280+
"Length of $name ($(length(idxs))) must match number of unrefined sections " *
1281+
"($U)"))
12781282
end
12791283

12801284
n_failed = Ref(0)
@@ -1302,8 +1306,8 @@ function linearize(solver::Solver{P, U}, body_aero::BodyAerodynamics, y::Vector{
13021306
end
13031307

13041308
va = isnothing(va_idxs) ? MVector{3, TI}(body_aero_c._va) : y_in[va_idxs]
1305-
om = isnothing(omega_idxs) ? MVector{3, TI}(body_aero_c.omega) : y_in[omega_idxs]
1306-
set_va!(body_aero_c, va, om)
1309+
omega = isnothing(omega_idxs) ? MVector{3, TI}(body_aero_c.omega) : y_in[omega_idxs]
1310+
set_va!(body_aero_c, va, omega)
13071311

13081312
solve!(solver_c, body_aero_c; kwargs...)
13091313
solver_c.lr.converged || (n_failed[] += 1)
@@ -1319,13 +1323,13 @@ function linearize(solver::Solver{P, U}, body_aero::BodyAerodynamics, y::Vector{
13191323
return nothing
13201324
end
13211325

1322-
n_results = 3 + 3 + length(solver.sol.moment_unrefined_dist)
1326+
n_results = 3 + 3 + U
13231327
jac = zeros(n_results, length(y))
13241328
results = zeros(n_results)
1325-
be = backend === nothing ?
1329+
ad_backend = backend === nothing ?
13261330
AutoFiniteDiff(absstep=fd_absstep, relstep=fd_relstep) : backend
1327-
prep = prepare_jacobian(calc_results!, results, be, y)
1328-
jacobian!(calc_results!, results, jac, prep, be, y)
1331+
prep = prepare_jacobian(calc_results!, results, ad_backend, y)
1332+
jacobian!(calc_results!, results, jac, prep, ad_backend, y)
13291333
calc_results!(results, y)
13301334
converged = n_failed[] == 0
13311335
if !converged

test/body_aerodynamics/test_body_aerodynamics.jl

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -513,15 +513,23 @@ function solve_wings(wings)
513513
end
514514

515515
"""
516-
linearize_wings(wings; kwargs...)
516+
wing_pair(section_y, n_panels, offset)
517517
518-
`linearize` at zero twist and deflection of the body [`solve_wings`](@ref) builds from
519-
`wings`, over the twist and the deflection of every unrefined section, then the inflow
520-
and the angular rate.
518+
Two `inviscid_wing`s of `n_panels` panels, the second shifted by `-offset` [m] in y.
521519
"""
522-
function linearize_wings(wings; kwargs...)
523-
n_sections = sum(wing -> wing.n_unrefined_sections, wings)
524-
body_aero = BodyAerodynamics(wings; va=[10.0, 0.0, 1.0])
520+
function wing_pair(section_y, n_panels, offset)
521+
return [inviscid_wing(section_y; n_panels),
522+
inviscid_wing(section_y .- offset; n_panels)]
523+
end
524+
525+
"""
526+
linearize_body(body_aero; kwargs...)
527+
528+
`linearize` of `body_aero` at zero twist and deflection over the twist and the deflection of
529+
every unrefined section, then the inflow and the angular rate.
530+
"""
531+
function linearize_body(body_aero; kwargs...)
532+
n_sections = sum(wing -> wing.n_unrefined_sections, body_aero.wings)
525533
solver = Solver(body_aero; use_gamma_prev=false, rtol=1e-10)
526534
y0 = [zeros(2n_sections); body_aero.va; zeros(3)]
527535
return VortexStepMethod.linearize(solver, body_aero, y0;
@@ -538,9 +546,7 @@ end
538546
@test single.solver_status == FEASIBLE
539547

540548
@testset "wings far apart each act as the isolated wing" begin
541-
wings = [inviscid_wing(section_y; n_panels),
542-
inviscid_wing(section_y .- 1e4; n_panels)]
543-
body_aero, sol = solve_wings(wings)
549+
body_aero, sol = solve_wings(wing_pair(section_y, n_panels, 1e4))
544550

545551
@test length(body_aero.panels) == 2n_panels
546552
@test sol.solver_status == FEASIBLE
@@ -552,9 +558,7 @@ end
552558
end
553559

554560
@testset "wings one chord apart induce on each other" begin
555-
wings = [inviscid_wing(section_y; n_panels),
556-
inviscid_wing(section_y .- (span + 1.0); n_panels)]
557-
_, sol = solve_wings(wings)
561+
_, sol = solve_wings(wing_pair(section_y, n_panels, span + 1.0))
558562
gamma = sol.gamma_distribution
559563

560564
@test sol.solver_status == FEASIBLE
@@ -563,31 +567,30 @@ end
563567
@test sol.force[3] > 2single.force[3]
564568
end
565569

566-
n_sections = 2length(section_y)
570+
n_wing_sections = length(section_y)
567571
@testset "linearize: theta of each wing moves that wing's sections" begin
568-
wings = [inviscid_wing(section_y; n_panels),
569-
inviscid_wing(section_y .- 1e4; n_panels)]
570-
jac, _, converged = linearize_wings(wings)
571-
wing_rows = (7:6+length(section_y), 7+length(section_y):6+n_sections)
572-
wing_columns = (1:length(section_y), length(section_y)+1:n_sections)
572+
body_aero, _ = solve_wings(wing_pair(section_y, n_panels, 1e4))
573+
jac, _, converged = linearize_body(body_aero)
574+
first_sections = 1:n_wing_sections
575+
second_sections = n_wing_sections+1:2n_wing_sections
576+
own_first = jac[6 .+ first_sections, first_sections]
573577

574578
@test converged
575-
@test norm(jac[wing_rows[1], wing_columns[1]]) > 0
576-
@test jac[wing_rows[2], wing_columns[2]] jac[wing_rows[1], wing_columns[1]] rtol=1e-4
577-
@test norm(jac[wing_rows[1], wing_columns[2]]) < 1e-4norm(jac[wing_rows[1], wing_columns[1]])
578-
@test norm(jac[wing_rows[2], wing_columns[1]]) < 1e-4norm(jac[wing_rows[1], wing_columns[1]])
579+
@test norm(own_first) > 0
580+
@test jac[6 .+ second_sections, second_sections] own_first rtol=1e-4
581+
@test norm(jac[6 .+ first_sections, second_sections]) < 1e-4norm(own_first)
582+
@test norm(jac[6 .+ second_sections, first_sections]) < 1e-4norm(own_first)
579583
end
580584

581585
@testset "linearize: AutoForwardDiff matches AutoFiniteDiff" begin
582-
wings = [inviscid_wing(section_y; n_panels),
583-
inviscid_wing(section_y .- (span + 1.0); n_panels)]
584-
jac_fwd, _, fwd_converged = linearize_wings(wings)
585-
jac_fd, _, fd_converged = linearize_wings(wings; backend=nothing,
586+
body_aero, _ = solve_wings(wing_pair(section_y, n_panels, span + 1.0))
587+
jac_fwd, _, fwd_converged = linearize_body(body_aero)
588+
jac_fd, _, fd_converged = linearize_body(body_aero; backend=nothing,
586589
fd_absstep=1e-6, fd_relstep=1e-6)
587590

588591
@test fwd_converged
589592
@test fd_converged
590-
@test norm(jac_fwd[:, 1:n_sections]) > 0
593+
@test norm(jac_fwd[:, 1:2n_wing_sections]) > 0
591594
@test jac_fwd jac_fd rtol=1e-4
592595
end
593596
end

0 commit comments

Comments
 (0)