Quickstart#

Input Structure#

An AVL geometry is a set of files that must travel together. The Bubble Dancer (examples/bd/) illustrates the typical structure: a sailplane with a fuselage body, four control surfaces (flap, aileron, elevator, rudder), and external airfoil coordinate files:

πŸ“ examples/bd/
β”œβ”€β”€ πŸ“„ bd.avl          ← geometry: surfaces, sections, control hinges, reference quantities
β”œβ”€β”€ πŸ“„ fuseBD.dat      ← fuselage body cross-section coordinates (referenced by bd.avl)
β”œβ”€β”€ πŸ“„ ag35.dat        ← airfoil coordinates (referenced by bd.avl AFIL entries)
β”œβ”€β”€ πŸ“„ ag36.dat
└── πŸ“„ ag37.dat

Project Layout#

Keep all these files together. AVL’s working directory is set to the folder containing the .avl file, so every relative path inside it (fuseBD.dat, ag35.dat, etc.) resolves automatically (relative to the .avl file, not your shell’s current directory). Moving the .avl file without its companions will cause AVL to silently produce geometry with missing surfaces.

For your own project, keep geometry inputs versioned in git and runs outside of version control:

πŸ“ my_project/               ← git repo
β”œβ”€β”€ πŸ“ _runs/                ← generated at runtime; add to .gitignore
β”‚   └── πŸ“ design_2026-05-15-143022/
β”œβ”€β”€ πŸ“ design/
β”‚   β”œβ”€β”€ πŸ“„ design.avl        ← geometry: surfaces, sections, control hinges
β”‚   β”œβ”€β”€ πŸ“„ wing_airfoil.dat  ← airfoil coordinates   (AFIL entry in .avl)
β”‚   └── πŸ“„ fuselage.dat      ← body cross-sections   (BFIL entry in .avl)
β”‚   └── πŸ“„ design.yml        ← CLI project file
β”œβ”€β”€ πŸ“„ analysis.py           ← Python API script
└── πŸ“„ .gitignore            ← contains: _runs/

See Directory Layout for the full contents of each timestamped run directory.

CLI#

The fastest path from geometry to results: define your sweep in a YAML project file, then run three commands.

See also

Project File#

Create a bd.yml alongside your .avl file:

examples/bd/bd.yml#
input:
  geometry: bd.avl

sweep:
  alpha: [-5, 0, 5, 10, 15]
  beta: [0]
  ctrl_sweeps:
    elevator: [-10, -5, 0, 5, 10]
    rudder:   [-10, 0, 10]
    aileron:  [-10, 0, 10]

output:
  format: csv

input.geometry is a path relative to the .yml file, so they should live in the same directory.

Plot Geometry#

Check that AVL reads the geometry correctly before running a sweep:

Input#
$ avl-aero-tables plot geometry examples/bd/bd.yml
Output#

Tip

The plots on this page are interactive thanks to plot.ly! Play with the toolbar to the top right of the image, drag and rotate 3dScatter content.

Run Sweep#

Input#
$ avl-aero-tables sweep examples/bd/bd.yml
Output#
AVL sweep complete β†’ /your/project/examples/_runs/bd/bd_2026-05-20-191250  (55 cases)

Note

While AVL runs, a Rich spinner (β Ή Running AVL...) animates in-place on the terminal, disappearing when the sweep finishes and leaving only the completion line. Pass --quiet to suppress all console output.

Results land in _runs/<yml-stem>/<avl-stem>_<timestamp>/ relative to the project root (one directory up from the .yml file). This differs from the Python API, where you control out_dir directly.

Plot Results#

AVL produces three categories of output per flight condition, each with its own plot subcommand. Pass a parent directory to use the latest sweep, or a specific timestamped directory to target a particular run.

See Data Categories for a full description of each category and its simulation use.

Total Coefficients#

Nonlinear 6-DOF table-lookup

Total force and moment coefficients (\(C_{(L,Y,D)_\mathrm{total}}\), \(C_{(l,m,n)_\mathrm{total}}\)) integrated at each flight condition. These are the tables a nonlinear 6-DOF simulation queries at each timestep, the primary output for flight dynamics work.

Input#
$ avl-aero-tables plot totals _runs/bd/
Output#
  β†’ total_stability.html
  β†’ total_control_CL.html
  β†’ total_control_CY.html
  β†’ total_control_CD.html
  β†’ total_control_Cl.html
  β†’ total_control_Cm.html
  β†’ total_control_Cn.html

Tip

The β€œStability” tab shows coefficients vs. \(\alpha\) and \(\beta\) at neutral controls. The \(C_L\)/\(C_Y\)/… tabs each show coefficient vs. \(\alpha\) and \(\delta\) for every control surface, sliced at \(\beta = 0Β°\) by default. To inspect a different sideslip, pass --beta-ref <deg>, e.g. avl-aero-tables plot totals --beta-ref 5 _runs/bd/.

Stability Derivatives#

Linear analysis: stability derivatives

Linearized \(\partial C_*/\partial(\alpha, \beta, p', q', r')\) at neutral controls. One figure per perturbation variable, six subplots per figure (\(C_L\), \(C_Y\), \(C_D\), \(C_l\), \(C_m\), \(C_n\)). Use these for stability analysis (phugoid, dutch roll, spiral) and linear plant model construction, not as table-lookup coefficients in a nonlinear sim.

Input#
$ avl-aero-tables plot stab-deriv _runs/bd/
Output#
  β†’ deriv_stability_alpha.html
  β†’ deriv_stability_beta.html
  β†’ deriv_stability_p.html
  β†’ deriv_stability_q.html
  β†’ deriv_stability_r.html

Control Derivatives#

Input#
$ avl-aero-tables plot ctrl-deriv _runs/bd/
Output#
  β†’ deriv_control_flap.html
  β†’ deriv_control_aileron.html
  β†’ deriv_control_elevator.html
  β†’ deriv_control_rudder.html

See also

See Aerodynamics for coefficient definitions, axis conventions, and how to recover dimensional forces and moments.

Python API#

See also

Read & Plot Geometry#

Input#
from avl_aero_tables import avl_fileread, avl_fileplot

geom = avl_fileread("examples/b737/b737.avl")

print(geom.header.name)          # 737-800 raised tail
print(list(geom.surface.keys())) # ['Wing', 'Stab', 'Fin', 'Fuselage_H', ...]
print(geom.ctrl_names)           # ['slat', 'flap', 'aileron', 'elevator', 'rudder']
print(geom.header.Sref)          # 1260.0  (reference area, sq-ft)

fig = avl_fileplot(geom)
fig.write_html("b737_geometry.html", include_plotlyjs="cdn")
Output#

Sweep Alpha / Beta#

out_dir is a base directory; avl_sweep creates _runs/b737_<timestamp>/ inside it automatically. The completion message and debug log are written to <run_dir>/<stem>.log (where <stem> is the .avl filename without extension, e.g. b737.log for b737.avl); nothing is printed to the console unless you configure logging yourself.

Input#
from pathlib import Path
from avl_aero_tables import avl_sweep

results = avl_sweep(
    avl_file="examples/b737/b737.avl",
    alpha=list(range(-6, 13, 2)),   # -6 to +12 deg, 2 deg steps
    beta=[0.0],
    out_dir=Path("_runs"),
)

print(f"{len(results)} cases computed")
for r in results[:3]:
    print(f"  Alpha={r.data['Alpha']:5.1f}  CLtot={r.data['CLtot']:.4f}")
Output#
10 cases computed
  Alpha= -6.0  CLtot=-0.4135
  Alpha= -4.0  CLtot=-0.2376
  Alpha= -2.0  CLtot=0.0362

Sweep Control Surfaces#

Input#
results = avl_sweep(
    avl_file="examples/b737/b737.avl",
    alpha=[-4.0, 0.0, 4.0, 8.0],
    beta=[0.0],
    ctrl_sweeps={"elevator": [-10.0, -5.0, 0.0, 5.0, 10.0]},
    out_dir=Path("_runs"),
)
print(f"{len(results)} cases (4 alpha Γ— 5 elevator deflections)")
Output#
20 cases (4 alpha Γ— 5 elevator deflections)

See also

See Concepts for how ctrl_sweeps counts cases and why 0.0 must be included for stability tables.

Build Aero Database#

Input#
from avl_aero_tables import aero_filewrite

results = avl_sweep(
    avl_file="examples/b737/b737.avl",
    alpha=list(range(-5, 16, 5)),
    beta=list(range(-5, 6, 5)),
    ctrl_sweeps={
        "slat":     [0.0, 5.0, 10.0],
        "flap":     [0.0, 10.0, 20.0],
        "aileron":  [-10.0, 0.0, 10.0],
        "elevator": [-10.0, 0.0, 10.0],
        "rudder":   [-10.0, 0.0, 10.0],
    },
    out_dir=Path("_runs"),
)

aero = aero_filewrite(results)
Output#
AeroDatabase: 5Ξ± Γ— 3Ξ²  |  Ξ΄_slat = 3, Ξ΄_flap = 3, Ξ΄_aileron = 3, Ξ΄_elevator = 3, Ξ΄_rudder = 3

Plot Aero Database#

Total Coefficients#

Nonlinear 6-DOF table-lookup

Total force and moment coefficients (\(C_{L,D,Y_\mathrm{total}}\) and \(C_{l,m,n_\mathrm{total}}\)), the primary output for flight dynamics work. The β€œStability” figure shows coefficients vs. \(\alpha\) and \(\beta\) at neutral controls; each subsequent figure shows one coefficient vs. \(\alpha\) and \(\delta\) for every control surface.

Input#
from avl_aero_tables import plot_totals

figs = plot_totals(aero, beta_ref=0.0)
for name, fig in figs.items():
    fig.write_html(f"b737_total_{name}.html", include_plotlyjs="cdn")
Output#

Tip

The control-surface figures show a \(\beta = 0Β°\) slice of the full 3-D table (\(\alpha \times \beta \times \delta\)). To inspect off-zero sideslip, pass beta_ref, e.g. plot_totals(aero, beta_ref=5.0).

Stability Derivatives#

Linear analysis: stability derivatives

Linearized \(\partial C_*/\partial(\alpha, \beta, p', q', r')\) at neutral controls. One figure per perturbation variable, six subplots per figure (\(C_L\), \(C_Y\), \(C_D\), \(C_l\), \(C_m\), \(C_n\)). Use these for stability analysis (phugoid, dutch roll, spiral) and linear plant model construction, not as look-up coefficients in a nonlinear sim.

Input#
from avl_aero_tables import plot_stab_derivs

for name, fig in plot_stab_derivs(aero).items():
    fig.write_html(f"b737_deriv_stab_{name}.html", include_plotlyjs="cdn")
Output#

Control Derivatives#

Input#
from avl_aero_tables import plot_ctrl_derivs

for surface, fig in plot_ctrl_derivs(aero).items():
    fig.write_html(f"b737_deriv_ctrl_{surface}.html", include_plotlyjs="cdn")
Output#

See also

See Aerodynamics for coefficient definitions, axis conventions, and how to recover dimensional forces and moments. See Data Categories for when to use totals vs. derivatives in simulation.