Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lifting line functions #41

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/src/guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,12 @@ r, c = lifting_line_geometry(grids)
cf, cm = lifting_line_coefficients(system, r, c; frame=Body())
nothing #hide
```
Alternatively, this block of code can be simplified by calling the single overloaded `lifting_line_coefficients` function with the `systems` array created earlier.
porter81nelson marked this conversation as resolved.
Show resolved Hide resolved
```
# lifting line geometry and lifting line coefficients are also combined in the single overloaded function
cf, cm = lifting_line_coefficients(system, surfaces; frame=Body())
nothing #hide
```
These coefficients are defined as ``c_f = \frac{F'}{q_\infty c}`` and ``c_m = \frac{M'}{q_\infty c^2}``, respectively, where ``F'`` is the force per unit length
along the lifting line, ``M'`` is the moment per unit length along the lifting line, ``q_\infty`` is the freestream dynamic pressure, and ``c`` is the local chord length.
By default, these coefficients are defined in the body frame, but may be returned in the stability or wind frame by using the `frame` keyword argument. Note that further manipulations upon these coefficients may be required to calculate local aerodynamic coefficients since 1) the local frame of reference is not necessarily equivalent to the global frame of reference and 2) the quantities used to normalize a given local aerodynamic coefficient may vary from those used in this package.
Expand Down
88 changes: 87 additions & 1 deletion src/geometry.jl
Original file line number Diff line number Diff line change
Expand Up @@ -903,6 +903,92 @@ function lifting_line_geometry!(r, c, grids, xc=0.25)
return r, c
end

"""
lifting_line_geometry(surfaces, xc=0.25)
Construct a lifting line representation of the surfaces in `grids` at the
normalized chordwise location `xc`. Return the lifting line coordinates
and chord lengths.
# Arguments
- `surfaces`: Vector of the surfaces to create lifting line from.
- `xc`: Normalized chordwise location of the lifting line from the leading edge.
Defaults to the quarter chord
# Return Arguments:
- `r`: Vector with length equal to the number of surfaces, with each element
being a matrix with size (3, ns+1) which contains the x, y, and z coordinates
of the resulting lifting line coordinates
- `c`: Vector with length equal to the number of surfaces, with each element
being a vector of length `ns+1` which contains the chord lengths at each
lifting line coordinate.
"""
function lifting_line_geometry(surfaces::Vector{Matrix{SurfacePanel{TF}}}, xc=0.25) where TF
porter81nelson marked this conversation as resolved.
Show resolved Hide resolved
nsurf = length(surfaces)
r = Vector{Matrix{TF}}(undef, nsurf)
c = Vector{Vector{TF}}(undef, nsurf)
for isurf = 1:nsurf
ns = size(surfaces[isurf], 2)
r[isurf] = Matrix{TF}(undef, 3, ns+1)
c[isurf] = Vector{TF}(undef, ns+1)
end
return lifting_line_geometry!(r, c, surfaces, xc)
end

"""
lifting_line_geometry!(r, c, surfaces, xc=0.25)
In-place version of [`lifting_line_geometry`](@ref)
"""
function lifting_line_geometry!(r, c, surfaces::Vector{Matrix{SurfacePanel{TF}}}, xc=0.25) where TF
porter81nelson marked this conversation as resolved.
Show resolved Hide resolved
nsurf = length(surfaces)
# iterate through each lifting surface
for isurf = 1:nsurf
# extract current grid
surface = surfaces[isurf]
# dimensions of this surface
nc = size(surface, 1)
ns = size(surface, 2)
# loop through each spanwise section
for j = 1:ns
# get leading and trailing edges
le = zeros(3)
le .= surface[end,j].rbl
prev_grid = zeros(3)
for i = nc:-1:1
grid_vec = zeros(3)
surface_vec = zeros(3)
surface_vec .= surface[i,j].rtl .- surface[i,j].rbl
grid_vec .= (surface_vec .- prev_grid * xc) / (1 - xc)
prev_grid .= grid_vec
le .+= grid_vec
end
# le = SVector(surface[1,1,j], surface[2,1,j], surface[3,1,j])
te = surface[end,j].rbl
# get quarter-chord
r[isurf][:,j] = linearinterp(xc, le, te)
# get chord length
c[isurf][j] = norm(le - te)
end

le = zeros(3)
le .= surface[end,end].rbr
prev_grid = zeros(3)
for i = nc:-1:1
grid_vec = zeros(3)
surface_vec = zeros(3)
surface_vec .= surface[i,end].rtr .- surface[i,end].rbr
grid_vec .= (surface_vec .- prev_grid * xc) / (1 - xc)
prev_grid .= grid_vec
le .+= grid_vec
end
# le = SVector(surface[1,1,end], surface[2,1,end], surface[3,1,end])
te = surface[end,end].rbr
# get quarter-chord
r[isurf][:,end] = linearinterp(xc, le, te)
# get chord length
c[isurf][end] = norm(le - te)

end
return r, c
end

"""
translate(grid, r)

Expand Down Expand Up @@ -1015,4 +1101,4 @@ end

Test whether and of the points in `args` are not on the symmetry plane (y = 0)
"""
not_on_symmetry_plane(args...; tol=eps()) = !on_symmetry_plane(args...; tol=tol)
not_on_symmetry_plane(args...; tol=eps()) = !on_symmetry_plane(args...; tol=tol)
40 changes: 40 additions & 0 deletions src/nearfield.jl
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,46 @@ function lifting_line_coefficients(system, r, c; frame=Body())
return lifting_line_coefficients!(cf, cm, system, r, c; frame)
end

"""
lifting_line_coefficients(system, surfaces; frame=Body())

Return the force and moment coefficients (per unit span) for each spanwise segment
of a lifting line representation of the geometry.

This function requires that a near-field analysis has been performed on `system`
to obtain panel forces.

# Arguments
- `system`: Object of type [`System`](@ref) that holds precalculated
system properties.
- `surfaces`: Vector with of surfaces in the system.

# Keyword Arguments
- `frame`: frame in which to return `cf` and `cm`, possible options are
[`Body()`](@ref) (default), [`Stability()`](@ref), and [`Wind()`](@ref)`

# Return Arguments:
- `cf`: Vector with length equal to the number of surfaces, with each element
being a matrix with size (3, ns) which contains the x, y, and z direction
force coefficients (per unit span) for each spanwise segment.
- `cm`: Vector with length equal to the number of surfaces, with each element
being a matrix with size (3, ns) which contains the x, y, and z direction
moment coefficients (per unit span) for each spanwise segment.
"""
function lifting_line_coefficients(system, surfaces; frame=Body())
r, c = lifting_line_geometry(surfaces)
TF = promote_type(eltype(system), eltype(eltype(r)), eltype(eltype(c)))
nsurf = length(system.surfaces)
cf = Vector{Matrix{TF}}(undef, nsurf)
cm = Vector{Matrix{TF}}(undef, nsurf)
for isurf = 1:nsurf
ns = size(system.surfaces[isurf], 2)
cf[isurf] = Matrix{TF}(undef, 3, ns)
cm[isurf] = Matrix{TF}(undef, 3, ns)
end
return lifting_line_coefficients!(cf, cm, system, r, c; frame)
porter81nelson marked this conversation as resolved.
Show resolved Hide resolved
end

"""
lifting_line_coefficients!(cf, cm, system, r, c; frame=Body())

Expand Down
8 changes: 7 additions & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -908,21 +908,27 @@ end

system = steady_analysis(surfaces, ref, fs; symmetric=symmetric)

# old method to generate lifting line coefficients
r_ll, c_ll = lifting_line_geometry(grids)

cf, cm = lifting_line_coefficients(system, r_ll, c_ll; frame=Stability())

# new overloaded function that calls lifting_line_geometry
alt_cf, alt_cm = lifting_line_coefficients(system, surfaces; frame=Stability())

cl_avl = [0.2618, 0.2646, 0.2661, 0.2664, 0.2654, 0.2628, 0.2584, 0.2513,
0.2404, 0.2233, 0.1952, 0.1434]
cd_avl = [0.0029, 0.0024, 0.0023, 0.0023, 0.0023, 0.0023, 0.0024, 0.0024,
0.0025, 0.0026, 0.0026, 0.0022]
cm_avl = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]

@test isapprox(cf, alt_cf, atol=1e-3, norm=(x)->norm(x, Inf))
@test isapprox(cm, alt_cm, atol=1e-3, norm=(x)->norm(x, Inf))
@test isapprox(cf[1][3,:], cl_avl, atol=1e-3, norm=(x)->norm(x, Inf))
@test isapprox(cf[1][1,:], cd_avl, atol=1e-4, norm=(x)->norm(x, Inf))
@test isapprox(cm[1][2,:], cm_avl, atol=1e-4, norm=(x)->norm(x, Inf))
end


@testset "Geometry Generation" begin

# Tests of the geometry generation functions
Expand Down