Stability derivatives with non-zero [p,q,r]
jdebecdelievre opened this issue · comments
Hi all,
I think that there is a small chain rule term forgotten in the stability derivatives computation with respect to alpha. It in stability_derivatives.jl
, in the stability_derivatives(system)
function.
Line 113, CF_a = CFs_a
should be CF_a = CFs_a + CFs_pb * pb_a + CFs_qb * qb_a + CFs_rb * rb_a
. Similarly, line 119, we should have CM_a = CMs_a + CMs_pb * pb_a + CMs_qb * qb_a + CMs_rb * rb_a
.
The reason would be that, when taking a partial derivative wrt alpha in the stability frame, we assume that the rotation rates in the stability frame do not change.
Below is a code snippet using the first example from the documentation to compare the analytic solution with finite differences. Note that I use fixed angular velocity in the stability frame when finite differencing.
I'm happy to do a pull request if you would like to incorporate the change.
Let me know if I'm missing something!
-Jean
using VortexLattice
function example1(alpha)
# geometry (right half of the wing)
xle = [0.0, 0.4]
yle = [0.0, 7.5]
zle = [0.0, 0.0]
chord = [2.2, 1.8]
theta = [2.0*pi/180, 2.0*pi/180]
phi = [0.0, 0.0]
fc = fill((xc) -> 0, 2) # camberline function for each section
# discretization parameters
ns = 12
nc = 6
spacing_s = Uniform()
spacing_c = Uniform()
# reference parameters
Sref = 30.0
cref = 2.0
bref = 15.0
rref = [0.50, 0.0, 0.0]
Vinf = 1.0
ref = Reference(Sref, cref, bref, rref, Vinf)
# freestream parameters
beta = 0.0
Omega_stability = [0.1; 0.2; 0.3]
Omega_body = VortexLattice.body_to_stability(sincos(alpha)...)' * Omega_stability
fs = Freestream(Vinf, alpha, beta, Omega_body)
# construct geometry with mirror image
grid, surface = wing_to_surface_panels(xle, yle, zle, chord, theta, phi, ns, nc;
fc=fc, spacing_s=spacing_s, spacing_c=spacing_c, mirror=true)
# symmetry is not used in the analysis
symmetric = false
# create vector containing all surfaces
surfaces = [surface]
# perform steady state analysis
system = steady_analysis(surfaces, ref, fs; symmetric=symmetric)
CF, CM = body_forces(system; frame=Stability())
dCF, dCM = stability_derivatives(system)
CL = CF[3]; CLα = dCF[1][3];
Cm = CM[2]; Cmα = dCM[1][2];
return CL, CLα, Cm, Cmα
end
# Use derivative computation
alpha = 1. * pi/180
_, CLα, _, Cmα = example1(alpha)
# Use finite differences
CL1, _, Cm1, _ = example1(alpha-1e-6)
CL2, _, Cm2, _ = example1(alpha+1e-6)
CLα_fd = (CL2-CL1)/2e-6
Cmα_fd = (Cm2-Cm1)/2e-6
println(
"""
CLα = $(CLα)
CLα_fd = $(CLα_fd)
Cmα = $(Cmα)
Cmα_fd = $(Cmα_fd)
"""
)
Returns:
CLα = 5.052638734014063
CLα_fd = 10.006357994279957
Cmα = -0.38029095592363177
Cmα_fd = -0.944973063028709
The discrepancy is large partly because I've used very large rotation rates. It is fixed with the change that have suggested above.
Since CM_a = CMs_a + CMs_pb * pb_a + CMs_qb * qb_a + CMs_rb * rb_a
now mixes derivatives around x, y, and z, the full fix requires to multiply every CM_...
by [ref.b, ref.c, ref.b]
, do all the calculations, and then re-divide by [ref.b, ref.c, ref.b]
at the end.
Thanks for the catch! I probably just forgot to keep the rotation rates in the stability frame constant when verifying the derivatives. It sounds like you have a good handle on the issue. If you're willing to put together a pull request for this I would greatly appreciate it.