How-to Guide

Airfoil Geometry

How to work with airfoil geometry.

Import Coordinates File

You can specify the path consisting of the foil's coordinates to the read_foil function. The Selig format for the coordinates file is followed, in which a header for the name in the first line of the file with the coordinates following from the second line are required. A custom name can be provided by setting the optional name variable.

# Airfoil coordinates file path
foilpath = string(@__DIR__, "/misc/s1223.dat")
"/home/runner/work/AeroFuse.jl/AeroFuse.jl/docs/build/misc/s1223.dat"

Note that, in this example, @__DIR__ points to the Julia REPL's current working directory. Use the correct local path for the coordinates on your computer.

# Read coordinates file
my_foil = read_foil(
    foilpath; # Path to the airfoil coordinates file
    name = "S1223" # To overwrite name in header
)
S1223 Foil{Float16} with 300 points.
plot(xlabel = L"x", ylabel = L"y", aspect_ratio = 1)
plot!(my_foil)
Tip

You can also import airfoil coordinates from the internet.

# Read coordinates from an internet address.
online_foil = read_foil(download("https://m-selig.ae.illinois.edu/ads/coord/s1210.dat"))

plot!(online_foil)

Interpolate and Process Coordinates

A basic cosine interpolation functionality is provided for foils.

# Cosine spacing with approx. 51 points on upper and lower surfaces each
cos_foil = cosine_interpolation(my_foil, 51)
S1223 Foil{Float64} with 99 points.

The upper and lower surfaces can be obtained by the following variety of functions.

# Upper surface
upper = upper_surface(my_foil)

# Lower surface
lower = lower_surface(my_foil)

# Upper and lower surfaces
upper, lower = split_surface(my_foil)
(Float16[-2.0e-5 -0.00073; -1.0e-5 0.00056; … ; 0.9976 0.00201; 1.0 0.0], Float16[-2.0e-5 -0.00073; 3.0e-5 -0.00202; … ; 0.997 0.00181; 1.0 0.0])

The camber-thickness distribution can be obtained as follows. It internally performs a cosine interpolation to standardize the $x$–coordinates for both surfaces; hence the number of points for the interpolation can be specified.

xcamthick = camber_thickness(my_foil, 60)
61×3 Matrix{Float64}:
 0.0          -0.00124659   0.0
 0.000685233  -9.97546e-5   0.0133951
 0.00273905    0.00142531   0.0254514
 0.00615583    0.00429351   0.0358441
 0.0109262     0.00779593   0.0455249
 0.0170371     0.0117405    0.0544609
 0.0244717     0.0157328    0.0629796
 0.0332098     0.0197507    0.0711215
 0.0432273     0.0239027    0.078745
 0.0544967     0.0281499    0.0859677
 ⋮                          
 0.956773      0.0258329    0.00703525
 0.96679       0.0215117    0.00653011
 0.975528      0.0171055    0.00556079
 0.982963      0.0126722    0.004475
 0.989074      0.00837342   0.00283016
 0.993844      0.00473417   0.0014028
 0.997261      0.00198852   0.000592446
 0.999315      0.000493805  0.000140883
 1.0           0.0          0.0

You can also do the inverse transformation.

coords = camber_thickness_to_coordinates(xcamthick[:,1], xcamthick[:,2], xcamthick[:,3])
121×2 Matrix{Float64}:
 1.0       0.0
 0.999315  0.000564246
 0.997261  0.00228474
 0.993844  0.00543557
 0.989074  0.0097885
 0.982963  0.0149097
 0.975528  0.0198859
 0.96679   0.0247768
 0.956773  0.0293506
 0.945503  0.0340995
 ⋮         
 0.956773  0.0223153
 0.96679   0.0182467
 0.975528  0.0143251
 0.982963  0.0104347
 0.989074  0.00695834
 0.993844  0.00403277
 0.997261  0.00169229
 0.999315  0.000423363
 1.0       0.0

Control Surfaces

You can (somewhat) mimic the behaviour of a control surface by specifying a deflection angle $\delta$ (in degrees, clockwise-positive convention) with the specification of the hinge location's $x$-coordinate normalized in $[0,1]$ to the chord length.

con_foil = control_surface(cos_foil; angle = 10., hinge = 0.75)

plot!(con_foil)

Doublet-Source Aerodynamic Analyses

The solve_case method runs the analysis given a Foil containing the airfoil coordinates, a Uniform2D defining the boundary conditions, and an optional named specification for the number of panels. It returns a system which can be used to obtain the aerodynamic quantities of interest and post-processing.

# Define freestream boundary conditions
uniform = Uniform2D(1.0, 4.0)

# Solve system
system  = solve_case(
    my_foil, # Foil
    uniform; # Freestream condition
    num_panels = 80
)
DoubletSourceSystem —
78 Panel2D{Float64} Elements
Freestream —
    alpha: 0.06981317007977318

The following functions compute the quantities of interest, such as the inviscid edge velocities, lift coefficient, and the sectional lift, moment, and pressure coefficients.

cls, cms, cps = surface_coefficients(system);
u_es   = surface_velocities(system)
cl     = lift_coefficient(system)
1.49218274070594

AeroFuse provides more helper functions for the panel geometry.

panels   = system.surface_panels
pts      = collocation_point.(panels) # Collocation points
tangents = tangent_vector.(panels)     # Tangents
normals  = normal_vector.(panels)      # Normals
locs     = panel_location.(panels);   # Upper or lower surface

Wing Geometry

How to work with wing geometry.

To define a wing, AeroFuse provides a Wing constructor based on the following parametrization. The named arguments correspond to the foil shapes, chord and span lengths, twist, dihedral and sweep angles.

Info

A wing section consists of two foil profiles and their chord lengths and twist angles. Between them is their span length with associated leading-edge dihedral and sweep angles. So a general half-wing consisting of $n$ sections will have $n$ entries for spans $b$, dihedrals $\delta$, sweeps $\Lambda$, and $n+1$ entries for foils, chords $c$, and twists $\iota$, for some $n \in \mathbb N$.

airfoil = naca4((2,4,1,2))
wing = Wing(
    foils     = [ airfoil for i in 1:3 ],   # Foils
    chords    = [0.4, 0.2, 0.1],  # Chord lengths
    twists    = [0., 2., 5.],     # Twist angles (degrees)
    spans     = [1.0, 0.1],       # Section span lengths
    dihedrals = [0., 60.],        # Dihedral angles (degrees)
    sweeps    = [0., 30.],        # Sweep angles (degrees)
    w_sweep   = 0.25,             # Sweep angle location w.r.t.
                                  # normalized chord lengths ∈ [0,1]
    symmetry  = true,             # Whether wing is symmetric
    # flip      = false           # Whether wing is flipped in x-z plane
)
Symmetric AbstractWing with 2 spanwise section(s).
Aspect Ratio: 7.684336828804395
Span (m): 2.2
Projected Area (m²): 0.6298526610464908
Mean Aerodynamic Chord (m): 0.3037157904580297
Mean Aerodynamic Center (m): [0.10257127268682563, 0.0, 0.0]
Position (m): [0.0, 0.0, 0.0]

The symmetry Boolean argument specifies whether the geometry should be reflected in the $x$-$z$ plane. The flip Boolean argument specifies whether the coordinates should be flipped in the $x$-$z$ plane. The w_sweep argument specifies the chordwise-ratio of the sweep angles, e.g. 0. = leading edge sweep angle (default), 1. = trailing edge, 0.25 = quarter-chord.

The following "getter" functions provide quantities of interest such as chord lengths, spans, twist, dihedral, and sweep angles.

julia> foils(wing)3-element Vector{Foil{Float64}}:
 NACA 2412 Foil{Float64} with 79 points.
 NACA 2412 Foil{Float64} with 79 points.
 NACA 2412 Foil{Float64} with 79 points.
julia> chords(wing)3-element Vector{Float64}: 0.4 0.2 0.1
julia> spans(wing)2-element Vector{Float64}: 1.0 0.1
julia> twists(wing)3-element Vector{Float64}: -0.0 -2.0 -5.0
julia> dihedrals(wing)2-element Vector{Float64}: 0.0 60.0
julia> sweeps(wing) # Leading-edge sweep angles2-element Vector{Float64}: 2.862405226111748 44.03624346792648
julia> sweeps(wing, 0.25) # Quarter-chord sweep angles2-element Vector{Float64}: 0.0 30.000000000000004
julia> sweeps(wing, 1.0) # Trailing-edge sweep angles2-element Vector{Float64}: -8.447527247908468 -0.9637565320735177

You can evaluate commonly defined properties such as the aspect ratio, projected area, etc., with the following functions.

julia> aspect_ratio(wing)7.684336828804395
julia> projected_area(wing)0.6298526610464908
julia> span(wing)2.2
julia> taper_ratio(wing)0.25
julia> mean_aerodynamic_chord(wing)0.3037157904580297

The mean aerodynamic center calculation merits discussion. Its calculation procedure is depicted in the following diagram:

mac25_w = mean_aerodynamic_center(wing) # 25% MAC by default
mac40_w = mean_aerodynamic_center(wing, 0.4) # at 40% MAC
3-element StaticArraysCore.SVector{3, Float64} with indices SOneTo(3):
 0.14812864125553007
 0.0
 0.0

You can plot the wing with Plots.jl quite simply.

plot(wing,
    0.25; # Aerodynamic center location in terms of chord ratio plot
    mac = true, # Optional named argument to disable aerodynamic center plot
    zlim = (-0.5, 0.5) .* span(wing),
    aspect_ratio = 1,
    label = "Wing",
)

At 40% MAC

plot!(wing,
    0.40; # 40% MAC
    label = "40% MAC"
)

There is also a convenient function for pretty-printing information (using PrettyTables.jl), in which the first argument takes the Wing type and the second takes a name (as a String or Symbol).

print_info(wing, "Wing")
───────────────────────────────────────────────────
            Wing                     Value
───────────────────────────────────────────────────
        Aspect Ratio                7.68434
          Span (m)                    2.2
          Area (m²)                 0.629853
 Mean Aerodynamic Chord (m)         0.303716
 Mean Aerodynamic Center (m)  [0.102571, 0.0, 0.0]
───────────────────────────────────────────────────
Tip

You can use Accessors.jl to conveniently copy and modify properties of an existing object.

# Import Accessors
using Accessors

# Set only chords with other properties remaining identical.
new_wing = @set wing.chords = [0.4, 0.1, 0.05]
Symmetric AbstractWing with 2 spanwise section(s).
Aspect Ratio: 9.399958877486162
Span (m): 2.2
Projected Area (m²): 0.5148958695545236
Mean Aerodynamic Chord (m): 0.27411982939806356
Mean Aerodynamic Center (m): [0.09129804700674422, 0.0, 0.0]
Position (m): [0.0, 0.0, 0.0]

Vortex Lattice Aerodynamic Analyses

How to run a generic aerodynamic analysis on a conventional aircraft configuration.

Geometry

First we define the lifting surfaces. These can be a combination of Wing types constructed using the various methods available.

Info

Support for fuselages and control surfaces is in progress.

Horizontal tail

htail = WingSection(
    area       = 2.56 / 2,
    aspect     = 6.25,
    dihedral   = 0.0,
    sweep      = 15.0,
    taper      = 0.6,
    root_twist = 0.0,
    tip_twist  = 0.0,
    root_foil  = naca4(0,0,1,2),
    tip_foil   = naca4(0,0,0,9),
    position   = [5., 0., -0.1],
    angle      = 0.,
    axis       = [0., 1., 0.],
    symmetry   = true
);

Vertical tail

vtail = WingSection(
    area       = 0.512 / 2,
    aspect     = 1.25,
    dihedral   = 0.0,
    sweep      = 8.0,
    taper      = 0.6,
    root_twist = 0.0,
    tip_twist  = 0.0,
    root_foil  = naca4(0,0,0,9),
    tip_foil   = naca4(0,0,0,9),
    position   = [5., 0., 0.],
    angle      = 90.,
    axis       = [1., 0., 0.]
)
AbstractWing with 1 spanwise section(s).
Aspect Ratio: 1.2500000000000002
Span (m): 0.565685424949238
Projected Area (m²): 0.25599999999999995
Mean Aerodynamic Chord (m): 0.46197643037521097
Mean Aerodynamic Center (m): [5.151932479252752, 1.5875861030984043e-17, 0.2592724864350674]
Position (m): [5.0, 0.0, 0.0]

Meshing

The WingMesh type takes a Wing type with a vector of integers consisting of the spanwise panel distribution corresponding to the number of sections, and an integer for the chordwise distribution.

# Wing meshes
wing_mesh = WingMesh(wing, [20,8], 10)
WingMesh —
Symmetric AbstractWing with 2 spanwise section(s).
Aspect Ratio: 7.684336828804395
Span (m): 2.2
Projected Area (m²): 0.6298526610464908
Mean Aerodynamic Chord (m): 0.3037157904580297
Mean Aerodynamic Center (m): [0.10257127268682563, 0.0, 0.0]
Position (m): [0.0, 0.0, 0.0]
Spanwise panels: [4, 10, 10, 4]
Chordwise panels: 10
Spanwise spacing: AbstractSpacing[Cosine(), Sine(true), Sine(false), Cosine()]
Chordwise spacing: Cosine()
Tip

Optionally ,the type of spanwise spacing can be specified by the keyword span_spacing and providing types Sine(), Cosine(), Uniform() or a vector of the combination with length corresponding to the number of sections. For example, if you have two spanwise sections and the wing is symmetric, then the total number of spanwise sections is four. So the spanwise spacing argument would be, for example, spanwise_spacing = [Uniform(), Cosine(), Cosine(), Uniform()]

# Horizontal tail
htail_mesh = WingMesh(htail, [10], 5;
                      span_spacing = Cosine()) # Uniform(), Sine()

# Vertical tail
vtail_mesh = WingMesh(vtail, [10], 5); # Vertical tail

Inviscid Analysis

The inviscid 3D analysis uses a vortex lattice method. The WingMesh type allows you to generate horseshoe elements easily.

wing_horsies = make_horseshoes(wing_mesh)
10×28 Matrix{Horseshoe{Float64}}:
 Horseshoe{Float64}([0.147303, -1.1, 0.173152], [0.133232, -1.08536, 0.147788], [0.141581, -1.09268, 0.160365], [-5.14387e-6, 0.000129292, 7.75726e-5], 0.0)  …  Horseshoe{Float64}([0.133232, 1.08536, 0.147788], [0.147303, 1.1, 0.173152], [0.141581, 1.09268, 0.160365], [-5.14387e-6, -0.000129292, 7.75726e-5], 0.0)
 Horseshoe{Float64}([0.150914, -1.1, 0.172837], [0.137372, -1.08536, 0.147482], [0.147954, -1.09268, 0.159855], [7.70584e-7, 0.000386787, 0.000223864], 0.0)     Horseshoe{Float64}([0.137372, 1.08536, 0.147482], [0.150914, 1.1, 0.172837], [0.147954, 1.09268, 0.159855], [7.70584e-7, -0.000386787, 0.000223864], 0.0)
 Horseshoe{Float64}([0.159006, -1.1, 0.172132], [0.146649, -1.08536, 0.146798], [0.158763, -1.09268, 0.15899], [7.86514e-6, 0.000604229, 0.000348141], 0.0)      Horseshoe{Float64}([0.146649, 1.08536, 0.146798], [0.159006, 1.1, 0.172132], [0.158763, 1.09268, 0.15899], [7.86514e-6, -0.000604229, 0.000348141], 0.0)
 Horseshoe{Float64}([0.170787, -1.1, 0.171105], [0.160155, -1.08536, 0.145801], [0.17295, -1.09268, 0.157854], [2.21062e-5, 0.000763618, 0.000437704], 0.0)      Horseshoe{Float64}([0.160155, 1.08536, 0.145801], [0.170787, 1.1, 0.171105], [0.17295, 1.09268, 0.157854], [2.21062e-5, -0.000763618, 0.000437704], 0.0)
 Horseshoe{Float64}([0.185103, -1.1, 0.169857], [0.176568, -1.08536, 0.14459], [0.189127, -1.09268, 0.15656], [3.92157e-5, 0.000846632, 0.000484017], 0.0)       Horseshoe{Float64}([0.176568, 1.08536, 0.14459], [0.185103, 1.1, 0.169857], [0.189127, 1.09268, 0.15656], [3.92157e-5, -0.000846632, 0.000484017], 0.0)
 Horseshoe{Float64}([0.200554, -1.1, 0.168511], [0.194282, -1.08536, 0.143282], [0.205709, -1.09268, 0.155233], [4.81742e-5, 0.00084226, 0.000483298], 0.0)   …  Horseshoe{Float64}([0.194282, 1.08536, 0.143282], [0.200554, 1.1, 0.168511], [0.205709, 1.09268, 0.155233], [4.81742e-5, -0.00084226, 0.000483298], 0.0)
 Horseshoe{Float64}([0.215627, -1.1, 0.167197], [0.211562, -1.08536, 0.142007], [0.221074, -1.09268, 0.154003], [5.06927e-5, 0.000754789, 0.000435409], 0.0)     Horseshoe{Float64}([0.211562, 1.08536, 0.142007], [0.215627, 1.1, 0.167197], [0.221074, 1.09268, 0.154003], [5.06927e-5, -0.000754789, 0.000435409], 0.0)
 Horseshoe{Float64}([0.228846, -1.1, 0.166045], [0.226717, -1.08536, 0.140888], [0.233717, -1.09268, 0.152992], [4.52099e-5, 0.000594927, 0.000345142], 0.0)     Horseshoe{Float64}([0.226717, 1.08536, 0.140888], [0.228846, 1.1, 0.166045], [0.233717, 1.09268, 0.152992], [4.52099e-5, -0.000594927, 0.000345142], 0.0)
 Horseshoe{Float64}([0.238918, -1.1, 0.165167], [0.238264, -1.08536, 0.140036], [0.242402, -1.09268, 0.152297], [3.14006e-5, 0.0003798, 0.000221404], 0.0)       Horseshoe{Float64}([0.238264, 1.08536, 0.140036], [0.238918, 1.1, 0.165167], [0.242402, 1.09268, 0.152297], [3.14006e-5, -0.0003798, 0.000221404], 0.0)
 Horseshoe{Float64}([0.244856, -1.1, 0.164649], [0.245072, -1.08536, 0.139534], [0.246277, -1.09268, 0.151986], [1.12597e-5, 0.000130445, 7.62554e-5], 0.0)      Horseshoe{Float64}([0.245072, 1.08536, 0.139534], [0.244856, 1.1, 0.164649], [0.246277, 1.09268, 0.151986], [1.12597e-5, -0.000130445, 7.62554e-5], 0.0)
Note

You can also generate vortex ring elements by calling make_vortex rings, but the aerodynamic analysis is slightly slower.

For multiple lifting surfaces, it is most convenient to define a single vector consisting of all the components' horseshoes using ComponentArrays.jl.

aircraft = ComponentVector(
    wing = wing_horsies,
    htail = make_horseshoes(htail_mesh),
    vtail = make_horseshoes(vtail_mesh)
);

To define boundary conditions, use the following Freestream type, which takes named arguments for angles of attack and sideslip (in degrees), and a quasi-steady rotation vector.

# Define freestream conditions
fs = Freestream(
    alpha = 1.0,
    beta  = 0.0,
    omega = [0.,0.,0.]
)
Freestream: 
    alpha = 0.017453292519943295
    beta = 0.0
    omega = [0.0, 0.0, 0.0]

To define reference values, use the following References type.

# Define reference values
refs = References(
    speed     = 150.0,
    density   = 1.225,
    viscosity = 1.5e-5,
    area      = projected_area(wing),
    span      = span(wing),
    chord     = mean_aerodynamic_chord(wing),
    location  = mean_aerodynamic_center(wing)
)
References: 
    Mach = 0.45454545454545453
    Reynolds = 3.720518433110864e6
    speed = 150.0
    density = 1.225
    viscosity = 1.5e-5
    sound_speed = 330.0
    area = 0.6298526610464908
    span = 2.2
    chord = 0.3037157904580297
    location = [0.10257127268682563, 0.0, 0.0]

The vortex lattice analysis can be executed with the vortex elements, freestream conditions, and reference values defined. An optional named argument is provided for enabling compressibility corrections at $M > 0.3$ via the Prandtl-Glauert transformation.

# Solve system
system = solve_case(
    aircraft, fs, refs;
    compressible = true, # Compressibility corrections via Prandtl-Glauert transformation
    print = true, # Prints the results for only the aircraft
    print_components = true, # Prints the results for all components
)
VortexLatticeSystem -
380 Horseshoe{Float64} Elements
Freestream: 
    alpha = 0.017453292519943295
    beta = 0.0
    omega = [0.0, 0.0, 0.0]
References: 
    Mach = 0.45454545454545453
    Reynolds = 3.720518433110864e6
    speed = 150.0
    density = 1.225
    viscosity = 1.5e-5
    sound_speed = 330.0
    area = 0.6298526610464908
    span = 2.2
    chord = 0.3037157904580297
    location = [0.10257127268682563, 0.0, 0.0]

If needed, you can access the relevant component influence matrix values and boundary conditions with the following attributes, e.g.

system.influence_matrix[:wing] # Or :htail, :vtail
system.influence_matrix[:wing, :htail];

system.boundary_vector[:wing]
10×28 Matrix{Float64}:
  3.37518e-6   1.38378e-5    2.18839e-5   …   1.38378e-5    3.37518e-6
 -4.1663e-6   -1.45893e-6    1.07025e-5      -1.45893e-6   -4.1663e-6
 -1.24165e-5  -1.99414e-5   -5.74997e-6      -1.99414e-5   -1.24165e-5
 -2.64917e-5  -5.74585e-5   -4.82687e-5      -5.74585e-5   -2.64917e-5
 -4.24492e-5  -0.000102692  -0.00010299      -0.000102692  -4.24492e-5
 -5.04163e-5  -0.000126442  -0.000133125  …  -0.000126442  -5.04163e-5
 -5.19149e-5  -0.000133243  -0.000144428     -0.000133243  -5.19149e-5
 -4.56287e-5  -0.000118944  -0.00013137      -0.000118944  -4.56287e-5
 -3.14068e-5  -8.26604e-5   -9.23305e-5      -8.26604e-5   -3.14068e-5
 -1.12132e-5  -2.96488e-5   -3.32944e-5      -2.96488e-5   -1.12132e-5

Forces and Moments

The analysis computes the aerodynamic force coefficients $C_{\mathbf{F}}$ by surface pressure integration for nearfield forces. The aerodynamic moment coefficients $C_{\mathbf M}$ are calculated by computing the cross product of the moment arm of each control point from the reference point $\mathbf r_i - \mathbf r_{ref}$, i.e. $(C_{\mathbf{M}})_i = (\mathbf r_i - \mathbf r_{ref}) \times (C_{\mathbf{F}})_i$

Note

You can specify the axis system for the nearfield forces, with choices of geometry, body, wind, or stability axes. The wind axes are used by default.

# Compute dynamics
ax = Wind() # Body(), Stability(), Geometry()

# Compute non-dimensional coefficients
CFs, CMs = surface_coefficients(system; axes = ax)
((wing = StaticArraysCore.SVector{3, Float64}[[-1.1592060275151364e-6, 0.00013838990119929145, 8.13677170183215e-5] [-8.874231726894972e-7, 0.0004074353861143275, 0.00023809650400401304] … [-8.87423172689494e-7, -0.0004074353861143274, 0.00023809650400401293] [-1.15920602751512e-6, -0.0001383899011992917, 8.136771701832165e-5]; [-1.1053927971495717e-6, 0.00020423816057873863, 0.00011971053947171981] [-1.152953183539759e-6, 0.0006241495203284984, 0.0003645952540669676] … [-1.1529531835397583e-6, -0.0006241495203284982, 0.00036459525406696744] [-1.1053927971495499e-6, -0.00020423816057873906, 0.0001197105394717201]; … ; [1.695193268127672e-6, 4.873646478769646e-5, 2.834398929143275e-5] [1.6241394716045617e-6, 0.00013547800920556656, 7.892515926622793e-5] … [1.6241394716045528e-6, -0.00013547800920556659, 7.892515926622794e-5] [1.6951932681276786e-6, -4.873646478769634e-5, 2.8343989291432685e-5]; [3.299627834323936e-7, 1.0349195944237907e-5, 6.031562183009532e-6] [3.2551372798721783e-7, 2.828426237018823e-5, 1.6489314075997117e-5] … [3.255137279872174e-7, -2.828426237018823e-5, 1.6489314075997117e-5] [3.299627834323945e-7, -1.034919594423791e-5, 6.031562183009534e-6]], htail = StaticArraysCore.SVector{3, Float64}[[-7.444571948338921e-6, -1.1070992152192308e-5, 0.0019751758956514493] [6.683607814246103e-6, -2.3129090324976267e-5, 0.005400390813406675] … [6.683607814250376e-6, 2.3129090324972828e-5, 0.005400390813406173] [-7.444571948337168e-6, 1.1070992152191323e-5, 0.0019751758956513357]; [2.2758771166897115e-6, -6.462126637748642e-6, 0.0016562040870071136] [1.5497604853736207e-5, -1.833088014120791e-5, 0.005216093071606387] … [1.5497604853740032e-5, 1.8330880141204685e-5, 0.005216093071605845] [2.2758771166905907e-6, 6.462126637747953e-6, 0.0016562040870070015]; … ; [3.202855879696425e-6, -2.509594969521897e-7, 0.0002773363864604541] [1.0702420574785029e-5, -1.6350845558075206e-6, 0.0012245719609140255] … [1.0702420574784871e-5, 1.6350845558070454e-6, 0.0012245719609138388] [3.2028558796961844e-6, 2.509594969521335e-7, 0.0002773363864604193]; [6.36514301065262e-7, -3.052970083199732e-8, 5.1115729869479864e-5] [2.291519267681156e-6, -2.040420391581627e-7, 0.00022919177990483896] … [2.291519267681071e-6, 2.0404203915809693e-7, 0.00022919177990480256] [6.365143010652085e-7, 3.052970083198975e-8, 5.111572986947316e-5]], vtail = StaticArraysCore.SVector{3, Float64}[[-4.000659737877759e-29, -7.04687290835271e-16, 5.99571456970629e-30] [-4.909434835274788e-28, -4.558404851705599e-15, 7.332578564613111e-29] … [-7.0591962715078965e-31, -1.6240688310415588e-16, 1.1500048723953164e-31] [-1.553299137773738e-31, -3.453966325461538e-17, 2.5231177633995456e-32]; [4.98958318081744e-29, 3.1920953821787407e-16, -4.7560596899423e-30] [2.050421761285824e-28, 9.784779941326775e-16, -1.9524136618562888e-29] … [-6.798122956823211e-31, -1.6959823896535447e-16, 7.493337137626024e-32] [-4.3313656225851117e-32, -3.907213169669541e-17, 6.507732473571876e-33]; … ; [3.02928198645433e-25, -1.03371278220952e-14, 3.892069137814474e-26] [3.8424274530313365e-28, -6.002850268054005e-15, 4.9733999661783527e-29] … [-2.9046256634538287e-31, -8.846181209256968e-17, -3.1914728902126816e-32] [4.715090408641916e-32, -4.839784430894879e-17, 9.014340908936877e-33]; [-3.826278810493687e-26, 7.929263326650677e-15, -8.13134603389094e-27] [1.8626756137253186e-28, 2.927060298547209e-15, 3.940341495990315e-29] … [-1.4164141690260087e-31, -3.230544729619133e-17, -2.8128374152161467e-32] [-2.1393553177179426e-31, -4.081385201426373e-17, -4.297193316232925e-32]]), (wing = StaticArraysCore.SizedVector{3, Float64, Vector{Float64}}[[5.04643960165894e-5, -1.1457792138756725e-5, -1.9713410314592163e-6] [0.00013720250986690608, -1.2664801161380478e-5, -2.4805364809175675e-6] … [-0.00013720250986690603, -1.2664801161380473e-5, 2.480536480917568e-6] [-5.046439601658949e-5, -1.1457792138756735e-5, 1.9713410314592295e-6]; [7.425573075422109e-5, -1.8065047228930863e-5, -3.5692210555021884e-6] [0.0002100030403220342, -2.5041487285910308e-5, -5.254012986445383e-6] … [-0.00021000304032203415, -2.5041487285910295e-5, 5.254012986445382e-6] [-7.425573075422128e-5, -1.8065047228930894e-5, 3.569221055502209e-6]; … ; [1.7405127102710345e-5, -1.210212160140574e-5, -3.9137227405339495e-6] [4.4912457031598865e-5, -3.497485676439714e-5, -9.212299297039884e-6] … [-4.491245703159887e-5, -3.497485676439714e-5, 9.212299297039881e-6] [-1.74051271027103e-5, -1.2102121601405705e-5, 3.913722740533946e-6]; [3.6993729382272233e-6, -2.7175770084619943e-6, -8.461073928069112e-7] [9.374287576908093e-6, -7.738695682856826e-6, -2.0176021082505e-6] … [-9.374287576908093e-6, -7.738695682856826e-6, 2.0176021082505e-6] [-3.699372938227225e-6, -2.717577008461995e-6, 8.461073928069116e-7]], htail = StaticArraysCore.SizedVector{3, Float64, Vector{Float64}}[[0.0012100344896892046, -0.0342295952858529, 3.1047363579906005e-5] [0.002708071499507147, -0.09245809827151164, 5.131516760432767e-5] … [-0.0027080714995068957, -0.09245809827150303, -5.131516760431742e-5] [-0.0012100344896891352, -0.034229595285850935, -3.104736357990259e-5]; [0.0010143819585714117, -0.02896333165891791, 1.4207170062013503e-5] [0.002615313803053016, -0.09020510948785035, 3.5993283778780117e-5] … [-0.0026153138030527443, -0.090205109487841, -3.59932837787705e-5] [-0.0010143819585713427, -0.028963331658915948, -1.4207170062011309e-5]; … ; [0.0001697889103733359, -0.005030568689980232, -1.3323972666991924e-6] [0.0006137624267870923, -0.022059199883958568, -1.2978988876619082e-6] … [-0.0006137624267869988, -0.022059199883955202, 1.297898887663013e-6] [-0.00016978891037331456, -0.005030568689979602, 1.3323972666991865e-6]; [3.129232469507389e-5, -0.0009396708804146492, -3.121852342388193e-7] [0.0001148632942331272, -0.0041908996340542645, -6.333557235898929e-7] … [-0.00011486329423310892, -0.004190899634053599, 6.333557235900164e-7] [-3.12923246950698e-5, -0.000939670880414526, 3.121852342388057e-7]], vtail = StaticArraysCore.SizedVector{3, Float64, Vector{Float64}}[[2.5241523165401093e-17, -8.657302997821264e-29, 1.5731223339784375e-15] [1.0745322908272887e-16, -1.1028479466500116e-27, 1.0184349674885482e-14] … [-3.283206093089252e-17, -2.9228253564661992e-30, 3.6830267827860606e-16] [-7.405518328402949e-18, -6.560423377217565e-31, 7.8391209337586e-17]; [-1.1625095224261383e-17, 6.492701895363767e-29, -7.235462782307072e-16] [-2.3640001020867077e-17, 2.8484716452853898e-28, -2.2190363478982108e-15] … [-3.422216650377842e-17, -2.23624509936363e-30, 3.882600919582829e-16] [-8.36308300568719e-18, -1.7512616771071761e-31, 8.949303132416085e-17]; … ; [4.0226635273922847e-16, -7.647474066343158e-25, 2.490933406762831e-14] [1.5972618703931963e-16, -9.415920379739514e-28, 1.445555224476828e-14] … [-1.7711681149514536e-17, 1.2870674954878674e-31, 2.1044818795097813e-16] [-1.0285737634824743e-17, -8.264877806034242e-32, 1.1506060177600085e-16]; [-3.1604943241123834e-16, 1.56164231495003e-25, -1.9535895863642198e-14] [-8.059419236811332e-17, -7.396204746016988e-28, -7.203942977164612e-15] … [-6.44902341705146e-18, 2.8681121605781057e-31, 7.794920481948716e-17] [-8.650534214875535e-18, 4.21794128238003e-31, 9.83720847744723e-17]]))

You can access the corresponding values of the components' by the name provided in the ComponentVector.

CFs.wing
10×28 reshape(view(::Vector{StaticArraysCore.SVector{3, Float64}}, 1:280), 10, 28) with eltype StaticArraysCore.SVector{3, Float64}:
 [-1.15921e-6, 0.00013839, 8.13677e-5]    …  [-1.15921e-6, -0.00013839, 8.13677e-5]
 [-1.10539e-6, 0.000204238, 0.000119711]     [-1.10539e-6, -0.000204238, 0.000119711]
 [1.2262e-6, 0.000203867, 0.000118253]       [1.2262e-6, -0.000203867, 0.000118253]
 [4.63886e-6, 0.000209934, 0.00012037]       [4.63886e-6, -0.000209934, 0.00012037]
 [6.94506e-6, 0.000209329, 0.00011958]       [6.94506e-6, -0.000209329, 0.00011958]
 [7.1121e-6, 0.000184144, 0.000105474]    …  [7.1121e-6, -0.000184144, 0.000105474]
 [5.93898e-6, 0.000149396, 8.60475e-5]       [5.93898e-6, -0.000149396, 8.60475e-5]
 [3.84756e-6, 0.000101061, 5.85346e-5]       [3.84756e-6, -0.000101061, 5.85346e-5]
 [1.69519e-6, 4.87365e-5, 2.8344e-5]         [1.69519e-6, -4.87365e-5, 2.8344e-5]
 [3.29963e-7, 1.03492e-5, 6.03156e-6]        [3.29963e-7, -1.03492e-5, 6.03156e-6]

Functions are available for directly retrieving the dimensionalized forces and moments.

Fs, Ms = surface_dynamics(system; axes = ax)
((wing = StaticArraysCore.SVector{3, Float64}[[-0.010062090296844042, 1.2012460675549874, 0.7062845572339073] [-0.007702972451113267, 3.536603112735582, 2.0667150323456935] … [-0.007702972451113239, -3.5366031127355813, 2.0667150323456926] [-0.0100620902968439, -1.2012460675549896, 0.7062845572339085]; [-0.009594983009398445, 1.7728192961606792, 1.0391062753791878] [-0.010007814629534761, 5.417715818593121, 3.1647440413043575] … [-0.010007814629534754, -5.417715818593119, 3.164744041304356] [-0.009594983009398254, -1.7728192961606832, 1.0391062753791902]; … ; [0.014714543687342985, 0.42304016525341825, 0.246030276632126] [0.014097785579138804, 1.175970387925954, 0.6850827725006916] … [0.014097785579138726, -1.1759703879259542, 0.6850827725006917] [0.014714543687343042, -0.4230401652534173, 0.24603027663212546]; [0.002864128759416226, 0.08983264546499627, 0.052354906613595244] [0.0028255102597169227, 0.24551183757949005, 0.14312983475539942] … [0.0028255102597169192, -0.24551183757949005, 0.14312983475539942] [0.0028641287594162344, -0.0898326454649963, 0.05235490661359526]], htail = StaticArraysCore.SVector{3, Float64}[[-0.06462005319805869, -0.09609794986125206, 17.1448368473353] [0.058014765054142714, -0.20076413494212464, 46.87624004097535] … [0.058014765054179795, 0.2007641349420948, 46.87624004097099] [-0.06462005319804348, 0.09609794986124352, 17.144836847334314]; [0.01975497065154272, -0.056092273672911856, 14.37611147449811] [0.1345216430226559, -0.15911491729976432, 45.2765067101592] … [0.1345216430226891, 0.1591149172997363, 45.27650671015449] [0.019754970651550352, 0.05609227367290588, 14.376111474497137]; … ; [0.027801291836245627, -0.002178367830433419, 2.407323372142392] [0.0928986907091305, -0.014192790628235044, 10.629476860220523] … [0.09289869070912912, 0.014192790628230919, 10.629476860218903] [0.02780129183624354, 0.002178367830432931, 2.40732337214209]; [0.005525044056473914, -0.0002650025959282553, 0.44369255967233884] [0.019890746977732264, -0.00177111693144195, 1.989420629256332] … [0.01989074697773153, 0.001771116931441379, 1.989420629256016] [0.005525044056473449, 0.0002650025959281896, 0.44369255967228066]], vtail = StaticArraysCore.SVector{3, Float64}[[-3.4726354568535743e-25, -6.116796309817591e-12, 5.204374370258384e-26] [-4.2614665078043284e-24, -3.956766971420428e-11, 6.364793304603205e-25] … [-6.127493182494668e-27, -1.4097172407962426e-12, 9.982222825960236e-28] [-1.3482880360614121e-27, -2.998096992607193e-13, 2.190105827806861e-28]; [4.33103652994453e-25, 2.770788902855492e-12, -4.1283344738952905e-26] [1.779798277351742e-24, 8.493342595485492e-12, -1.6947257084662965e-25] … [-5.900877446887705e-27, -1.472139338606784e-12, 6.504334269647628e-28] [-3.7596933563674404e-28, -3.3915223686774513e-13, 5.648813948729181e-29]; … ; [2.6294643194398465e-21, -8.972789227028285e-11, 3.378377111288598e-22] [3.335287349596613e-24, -5.2105682684439945e-11, 4.316989245585531e-25] … [-2.5212606741575392e-27, -7.678624161452298e-13, -2.7702485700567598e-28] [4.092772494570102e-28, -4.2010088633953674e-13, 7.824589420630293e-29]; [-3.3212700743643925e-22, 6.882725045110351e-11, -7.058136007391228e-23] [1.6168316739354445e-24, 2.5407342896088176e-11, 3.4202782759890694e-25] … [-1.2294697342990584e-27, -2.8041635400310134e-13, -2.4415870337489853e-28] [-1.8569940004586742e-27, -3.5427064264828396e-13, -3.73003125799963e-28]]), (wing = StaticArraysCore.SVector{3, Float64}[[0.9636855350750632, -0.030206185894323192, -0.03764540917308684] [2.6200665136518366, -0.033388224673868955, -0.04736918133530091] … [-2.6200665136518353, -0.03338822467386894, 0.04736918133530092] [-0.9636855350750649, -0.030206185894323216, 0.03764540917308709]; [1.41801307996924, -0.04762489737800608, -0.06815907796740676] [4.010290586131285, -0.06601689146287958, -0.10033244655240686] … [-4.010290586131284, -0.06601689146287953, 0.10033244655240685] [-1.4180130799692434, -0.047624897378006154, 0.06815907796740715]; … ; [0.33237431831168673, -0.03190483213351718, -0.07473780112432231] [0.8576637907605991, -0.09220424076984016, -0.17592124900139658] … [-0.8576637907605992, -0.09220424076984018, 0.17592124900139652] [-0.33237431831168596, -0.03190483213351709, 0.07473780112432224]; [0.07064450327010276, -0.00716435027845155, -0.016157558990700108] [0.17901463313918287, -0.02040152915545336, -0.03852882667254728] … [-0.17901463313918287, -0.02040152915545336, 0.03852882667254728] [-0.07064450327010278, -0.007164350278451552, 0.016157558990700118]], htail = StaticArraysCore.SVector{3, Float64}[[23.107236521211647, -90.23950738245055, 0.5928911776599097] [51.71426863339779, -243.7473528934107, 0.9799321631430321] … [-51.714268633393, -243.74735289338804, -0.9799321631428362] [-23.10723652121032, -90.23950738244538, -0.5928911776598444]; [19.370988215038345, -76.3560526856566, 0.2713050261933802] [49.94293562645277, -237.80779689580274, 0.687340177935742] … [-49.942935626447586, -237.80779689577807, -0.6873401779355583] [-19.370988215037034, -76.35605268565143, -0.27130502619333835]; … ; [3.24234767199337, -13.26209196008274, -0.02544391837107222] [11.720619275277768, -58.15468497818179, -0.024785125410371006] … [-11.720619275275983, -58.154684978172924, 0.0247851254103921] [-3.2423476719929627, -13.26209196008108, 0.025443918371072106]; [0.5975690397166665, -2.4772550374061106, -0.005961597051534535] [2.193469136679002, -11.048471806578824, -0.012094779637904209] … [-2.1934691366786527, -11.048471806577071, 0.012094779637906568] [-0.5975690397165883, -2.477255037405786, 0.005961597051534276]], vtail = StaticArraysCore.SVector{3, Float64}[[4.820208439582378e-13, -2.2823254299675764e-25, 3.0040887394355865e-11] [2.051963973374259e-12, -2.9074388578756e-24, 1.9448385873095935e-10] … [-6.269723746501027e-13, -7.705446650181546e-27, 7.033235144037396e-12] [-1.414183356215962e-13, -1.7295249004159375e-27, 1.4969856072554354e-12]; [-2.2199683332795853e-13, 1.7116714811433404e-25, -1.38170896181758e-11] [-4.5143762397315224e-13, 7.509427906372842e-25, -4.237548448161982e-11] … [-6.535183107666667e-13, -5.8954146103035055e-27, 7.414348808298657e-12] [-1.597043214103549e-13, -4.616852455314622e-28, 1.7089898341151693e-12]; … ; [7.681817201473307e-12, -2.0161041540333164e-21, 4.756772462199823e-10] [3.0501864318733865e-12, -2.4823197865013812e-24, 2.7604821813830045e-10] … [-3.382283802631427e-13, 3.3930969908017593e-28, 4.018791278992946e-12] [-1.9641999823002553e-13, -2.178870347616776e-28, 2.197236989661251e-12]; [-6.035389114401979e-12, 4.116958790538883e-22, -3.7306421446787617e-10] [-1.5390545320442527e-12, -1.9498620045214643e-24, -1.3756898309685376e-10] … [-1.2315277845255133e-13, 7.561206211373272e-28, 1.4885449363239998e-12] [-1.6519358897720697e-13, 1.1119761724071219e-27, 1.878547305335287e-12]]))

A Trefftz plane integration is performed to compute farfield forces.

Note

The farfield forces are usually more accurate compared to nearfield forces.

To obtain the nearfield coefficients of the components (in wind axes by definition):

nfs = nearfield_coefficients(system)
(wing = 6-element LabelledArrays.SLArray{Tuple{6}, Float64, 1, 6, (:CX, :CY, :CZ, :Cl, :Cm, :Cn)} with indices SOneTo(6):
 :CX => 0.003957539725248549
 :CY => 2.659683454378503e-19
 :CZ => 0.3450556800095911
 :Cl => -3.883773118103055e-17
 :Cm => -0.05858161327748091
 :Cn => 7.327893784933766e-19, htail = 6-element LabelledArrays.SLArray{Tuple{6}, Float64, 1, 6, (:CX, :CY, :CZ, :Cl, :Cm, :Cn)} with indices SOneTo(6):
 :CX => 0.0003325950091132945
 :CY => -1.7750422442661118e-17
 :CZ => 0.05310212695226438
 :Cl => 3.827050709757224e-15
 :Cm => -0.9209847143167331
 :Cn => 6.738835309677603e-18, vtail = 6-element LabelledArrays.SLArray{Tuple{6}, Float64, 1, 6, (:CX, :CY, :CZ, :Cl, :Cm, :Cn)} with indices SOneTo(6):
 :CX => 3.076521523839102e-25
 :CY => -2.2580903467955257e-14
 :CZ => 2.4452796355715344e-26
 :Cl => -1.3076972347366828e-15
 :Cm => -5.067076369276467e-25
 :Cn => 4.9104706390848985e-14)

Similarly for the farfield coefficients of the components.

ffs = farfield_coefficients(system)
(wing = 3-element LabelledArrays.SLArray{Tuple{3}, Float64, 1, 3, (:CDi, :CY, :CL)} with indices SOneTo(3):
 :CDi => 0.00452868276797213
  :CY => 5.8755700250094325e-19
  :CL => 0.3450392015240493, htail = 3-element LabelledArrays.SLArray{Tuple{3}, Float64, 1, 3, (:CDi, :CY, :CL)} with indices SOneTo(3):
 :CDi => 0.00035475639005410123
  :CY => -3.8924503843416984e-17
  :CL => 0.05333572825102704, vtail = 3-element LabelledArrays.SLArray{Tuple{3}, Float64, 1, 3, (:CDi, :CY, :CL)} with indices SOneTo(3):
 :CDi => 9.198483658448506e-28
  :CY => -2.264876361849759e-14
  :CL => 1.3868367935019049e-30)

You can access the values corresponding to the components by the name used in the ComponentArray construction.

@show (nfs.wing, ffs.wing)
(6-element LabelledArrays.SLArray{Tuple{6}, Float64, 1, 6, (:CX, :CY, :CZ, :Cl, :Cm, :Cn)} with indices SOneTo(6):
 :CX => 0.003957539725248549
 :CY => 2.659683454378503e-19
 :CZ => 0.3450556800095911
 :Cl => -3.883773118103055e-17
 :Cm => -0.05858161327748091
 :Cn => 7.327893784933766e-19, 3-element LabelledArrays.SLArray{Tuple{3}, Float64, 1, 3, (:CDi, :CY, :CL)} with indices SOneTo(3):
 :CDi => 0.00452868276797213
  :CY => 5.8755700250094325e-19
  :CL => 0.3450392015240493)

To obtain the total nearfield and farfield force coefficients:

nf, ff = nearfield(system), farfield(system)
(6-element LabelledArrays.SLArray{Tuple{6}, Float64, 1, 6, (:CX, :CY, :CZ, :Cl, :Cm, :Cn)} with indices SOneTo(6):
 :CX => 0.004290134734361843
 :CY => -2.259890066814083e-14
 :CZ => 0.3981578069618555
 :Cl => 2.481189558549053e-15
 :Cm => -0.9795663275942137
 :Cn => 4.91122041676794e-14, 3-element LabelledArrays.SLArray{Tuple{3}, Float64, 1, 3, (:CDi, :CY, :CL)} with indices SOneTo(3):
 :CDi => 0.0048834391580262326
  :CY => -2.2687100565338506e-14
  :CL => 0.3983749297750763)

You can also print the relevant information as a pretty table, if necessary.

print_coefficients(nfs.wing, ffs.wing, :wing)
print_coefficients(nf, ff, :aircraft)
────────────────────────────────────
 wing  Nearfield          Farfield
────────────────────────────────────
  CX   0.00395754  CDi   0.00452868
  CY      0.0      CYff     0.0
  CZ    0.345056    CL    0.345039
  Cl      -0.0               —
  Cm   -0.0585816            —
  Cn      0.0                —
────────────────────────────────────
────────────────────────────────────────
 aircraft  Nearfield          Farfield
────────────────────────────────────────
    CX     0.00429013  CDi   0.00488344
    CY        -0.0     CYff     -0.0
    CZ      0.398158    CL    0.398375
    Cl        0.0                —
    Cm     -0.979566             —
    Cn        0.0                —
────────────────────────────────────────

Aerodynamic Stability Analyses

The derivatives of the aerodynamic coefficients with respect to the freestream values are obtained by automatic differentiation enabled by ForwardDiff. The following function evaluates the derivatives of the aerodynamic coefficients with respect to the freestream values. You can also optionally provide the axes for the reference frame of the coefficients.

dv_data = freestream_derivatives(
    system,
    print = true,  # Prints the results for only the aircraft
    print_components = true,  # Prints the results for all components
);
──────────────────────────────────────────────────────────────────────────────────────────────
 wing    Values                             Freestream   Derivatives
                      ∂/∂M     ∂/∂α, 1/rad  ∂/∂β, 1/rad     ∂/∂p̄         ∂/∂q̄        ∂/∂r̄
──────────────────────────────────────────────────────────────────────────────────────────────
  CX   0.00395754  0.00347335    0.11771        0.0         -0.0      -0.0492756     -0.0
  CY      0.0         0.0          0.0       -0.142373    -0.264392      0.0       0.0918817
  CZ    0.345056    0.151508      5.472         0.0         -0.0       10.9144       -0.0
  Cℓ      0.0         0.0          0.0      -0.0418825    -0.555361      -0.0      0.109052
  Cm   -0.0585816  -0.0319284   0.0299961      -0.0          0.0      -0.906578       0.0
  Cn      -0.0        -0.0        -0.0      -0.0080398   -0.0253157      -0.0     -0.00233701
──────────────────────────────────────────────────────────────────────────────────────────────
─────────────────────────────────────────────────────────────────────────────────────────────
 htail   Values                              Freestream   Derivatives
                      ∂/∂M      ∂/∂α, 1/rad  ∂/∂β, 1/rad     ∂/∂p̄        ∂/∂q̄       ∂/∂r̄
─────────────────────────────────────────────────────────────────────────────────────────────
  CX    0.0003326  -0.00052487    0.12502       -0.0          0.0      3.72439      -0.0
  CY       0.0         0.0          0.0      0.00230357    0.014003      0.0     0.00244072
  CZ    0.0531021  -0.0343939     8.53404       -0.0         -0.0      403.809      -0.0
  Cℓ      -0.0        -0.0         -0.0       -0.203665    -1.42212      -0.0     -0.52356
  Cm    -0.920985   0.577482     -145.723        0.0          0.0      -6896.25      0.0
  Cn       0.0         0.0         -0.0      -0.0069241    -0.038453     -0.0    -0.00135864
─────────────────────────────────────────────────────────────────────────────────────────────
────────────────────────────────────────────────────────────────────────────
 vtail  Values                     Freestream   Derivatives
                ∂/∂M  ∂/∂α, 1/rad  ∂/∂β, 1/rad     ∂/∂p̄      ∂/∂q̄    ∂/∂r̄
────────────────────────────────────────────────────────────────────────────
  CX     -0.0   -0.0      0.0         -0.0          0.0      0.0     0.0
  CY     0.0    0.0     2.0e-8      -1.02913     0.332084    0.0   4.76381
  CZ     -0.0   -0.0      0.0         -0.0          0.0      0.0     0.0
  Cℓ     0.0    0.0       0.0      -0.0875382   0.00660004   0.0   0.441621
  Cm     0.0    0.0      -0.0          0.0         -0.0      -0.0    -0.0
  Cn     -0.0   -0.0    -4.0e-8      2.30749     -0.611054   -0.0  -10.9476
────────────────────────────────────────────────────────────────────────────
──────────────────────────────────────────────────────────────────────────────────────────────
 aircraft    Values                             Freestream   Derivatives
                          ∂/∂M     ∂/∂α, 1/rad  ∂/∂β, 1/rad     ∂/∂p̄        ∂/∂q̄      ∂/∂r̄
──────────────────────────────────────────────────────────────────────────────────────────────
    CX     0.00429013  0.00294848    0.24273       -0.0          0.0      3.67512      0.0
    CY        0.0         0.0        2.0e-8       -1.1692     0.0816947     0.0      4.85813
    CZ      0.398158    0.117114     14.006        -0.0          0.0      414.723      0.0
    Cℓ        -0.0        -0.0        -0.0       -0.333086    -1.97088      -0.0    0.0271125
    Cm     -0.979566    0.545553    -145.693        0.0         -0.0      -6897.15    -0.0
    Cn        -0.0        -0.0       -4.0e-8      2.29253     -0.674823     -0.0    -10.9513
──────────────────────────────────────────────────────────────────────────────────────────────
Note

For efficiency, instead of calling solve_case to compute the forces and then computing the derivatives, you can directly call:

dvs = freestream_derivatives(
          aircraft, fs, refs,
          compressible     = true, # Compressibility option
          print            = true, # Prints the results for only the aircraft
          print_components = true, # Prints the results for all components
      )

This page was generated using Literate.jl.