Skip to content

Commit a81fbe7

Browse files
1-Bort-1claude
andcommitted
Check POLAR_MATRICES forwarddiff on affine tables instead of NeuralFoil's
The ram-air wing's tip sections are ~70%-thick slices (#361) on which NeuralFoil returns Cd=1 at every alpha, and those outputs differ with the runner's CPU, so the LOOP solve lands on one of two different solutions depending on the runner. Tables that are affine in (alpha, delta) make the bilinear interpolation exact, keep every panel attached, and are the same bits on every machine. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent 9ed3cd6 commit a81fbe7

1 file changed

Lines changed: 24 additions & 16 deletions

File tree

test/solver/test_forwarddiff.jl

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,25 @@ using Test
55

66
relative_error(jac, reference) = maximum(abs.(jac .- reference)) / maximum(abs, reference)
77

8+
# Four-section arc whose POLAR_MATRICES tables are affine in (alpha, delta), so the
9+
# bilinear interpolation is exact and has no kinks at the grid knots.
10+
function affine_matrix_wing(n_panels)
11+
alphas = deg2rad.(-5:5:25)
12+
deltas = deg2rad.(-3:3:3)
13+
cl = [0.2 + 5.5alpha + 1.5delta for alpha in alphas, delta in deltas]
14+
cd = [0.03 + 0.2alpha + 0.05delta for alpha in alphas, delta in deltas]
15+
cm = [-0.05 - 0.1alpha - 0.3delta for alpha in alphas, delta in deltas]
16+
wing = Wing(n_panels, spanwise_distribution=LINEAR)
17+
radius = 3.0
18+
for phi in deg2rad.((50, 17, -17, -50))
19+
le = [0.0, radius * sin(phi), radius * (cos(phi) - 1)]
20+
add_section!(wing, le, le .+ [1.0, 0.0, 0.0], POLAR_MATRICES,
21+
(alphas, deltas, cl, cd, cm))
22+
end
23+
refine!(wing)
24+
return wing
25+
end
26+
827
@testset "ForwardDiff linearize" begin
928
n_panels = 10
1029
span = 20.0
@@ -57,20 +76,9 @@ relative_error(jac, reference) = maximum(abs.(jac .- reference)) / maximum(abs,
5776
end
5877

5978
@testset "AutoForwardDiff matches AutoFiniteDiff (LOOP, POLAR_MATRICES)" begin
60-
# At this operating point the LOOP solve converges the mid-span
61-
# panels' local alpha to ~6.5-9.1deg and the tip panels' to
62-
# ~14.9-15.0deg. The default 5deg-spaced alpha_range=-5:5:15 puts the
63-
# tip cluster within ulp-scale distance of the 15deg knot on some
64-
# platforms (Windows, Julia 1.12), so AutoForwardDiff and the FD
65-
# reference land on opposite sides of that non-differentiable kink
66-
# and disagree by several percent (#360). Offset the grid so no knot
67-
# is near either cluster (margin >0.8deg here vs <0.04deg before).
68-
ram_wing = ram_air_matrix_wing(; n_panels=8, n_sections=4,
69-
alpha_range=deg2rad.(-2:5:23),
70-
delta_range=deg2rad.(-3:3:3),
71-
)
72-
ram_body = BodyAerodynamics([ram_wing])
73-
ram_solver = Solver(ram_wing.n_panels, ram_wing.n_unrefined_sections;
79+
matrix_wing = affine_matrix_wing(8)
80+
matrix_body = BodyAerodynamics([matrix_wing])
81+
matrix_solver = Solver(matrix_wing.n_panels, matrix_wing.n_unrefined_sections;
7482
aerodynamic_model_type=VSM,
7583
rtol=1e-11,
7684
solver_type=LOOP,
@@ -84,13 +92,13 @@ relative_error(jac, reference) = maximum(abs.(jac .- reference)) / maximum(abs,
8492
zeros(3)]
8593

8694
jac_fwd, _, conv_fwd = VortexStepMethod.linearize(
87-
ram_solver, ram_body, y_op;
95+
matrix_solver, matrix_body, y_op;
8896
theta_idxs=1:4, va_vec_idxs=5:7, omega_idxs=8:10,
8997
aero_coeffs=true, backend=AutoForwardDiff())
9098
@test conv_fwd
9199

92100
jac_fd, _, conv_fd = VortexStepMethod.linearize(
93-
ram_solver, ram_body, y_op;
101+
matrix_solver, matrix_body, y_op;
94102
theta_idxs=1:4, va_vec_idxs=5:7, omega_idxs=8:10,
95103
aero_coeffs=true, backend=nothing)
96104
@test conv_fd

0 commit comments

Comments
 (0)