Ptera Software is a fast, easy-to-use, and open-source package for analyzing flapping-wing flight using unsteady and steady vortex lattice methods.
- Multiple Simulation Methods: Steady horseshoe VLM, steady ring VLM, and unsteady ring UVLM
- Customizable Aircraft Geometry: Multi-wing aircraft with arbitrary wing cross sections and airfoils
- Time-Dependent Motion: Custom prescribed flapping motions
- Formation Flight: Multi-airplane simulations supported since v2.0.0
- High-Speed Computing: JIT compilation via Numba for fast simulations
- Trim Analysis: Automatic search for trim operating points
- Convergence Analysis: Automatic search for converged parameters
- Aeroelasticity: First-order structural wing deformation coupled to the UVLM via a torsional spring-mass-damper model (beta)
- Free Flight: Six-degree-of-freedom flight dynamics from UVLM aerodynamics coupled to MuJoCo rigid-body dynamics (beta)
- Visualization Tools: 3D mesh visualization and 2D plotting of results
- Save and Load: JSON serialization of solved simulations without pickle security risks
- Extensive Testing: Comprehensive unit and integration tests for reliability
Requires Python 3.11, but active development is done in 3.14
- NumPy/SciPy: Core numerical computations
- Numba: JIT compilation for performance-critical loops
- PyVista: 3D mesh processing and visualization
- Matplotlib: 2D plotting and analysis output
.github/: Directory with GitHub configuration files: the issue and pull request templates, the label definitions (labels.yml), the Dependabot, funding, and code-owner configuration, and the GitHub Actions workflows (ascii-only.yml,ci.yml,label-sync.yml,pre-commit-hooks.yml,publish.yml, andzizmor.yml).venv/: Directory for the Python virtual environment, configured for the host machine's OS (not included in version control).venv-wsl/: Directory for the Python virtual environment configured for a WSL OS (not included in version control, may be missing if host machine doesn't use WSL for development)experimental/: Directory with experimental scripts and prototypes (not included in version control)docs/: Directory with documentation filesexamples_expected_output/: Example output files for verificationhero_graphics/: Assets for the README hero graphicprivate/: Directory with documentation not included in this repository's version control (may be missing if the private repo hasn't been cloned and linked to this local repo)katz_plotkin_12_2/: A recreation of Chapter 12.2, which describes efficiently including the effects of symmetry and ground effect for vortex lattice methods, from the textbook "Low-Speed Aerodynamics" by Katz and Plotkinkatz_plotkin_13_12/: A recreation of Chapter 13.12, which describes the UVLM, from the textbook "Low-Speed Aerodynamics" by Katz and Plotkinkatz_plotkin_app_d/: A recreation of Appendix D, which includes example Fortran programs, from the textbook "Low-Speed Aerodynamics" by Katz and Plotkinlambert_2015_2_3__2_4/: A recreation of Sections 2.3 and 2.4 from Thomas Lambert's thesis "Modeling of aerodynamic forces in flapping flight with the unsteady vortex lattice method"
website/: Directory with the source files for generating the documentation websiteANGLE_VECTORS_AND_TRANSFORMATIONS.md: Conventions and definitions for angle vectors and transformations READ BEFORE CONTRIBUTING ANY CODE, PARTICIPATING IN DISCUSSIONS REGARDING, OR PLANNING RELATED TO VECTOR-VALUED VARIABLESAXES_POINTS_AND_FRAMES.md: Conventions and definitions for axis systems, points, and reference points: READ BEFORE CONTRIBUTING ANY CODE, PARTICIPATING IN DISCUSSIONS REGARDING, OR PLANNING RELATED TO VECTOR-VALUED VARIABLESCLASSES_AND_IMMUTABILITY.md: Description of class structure and attribute immutability.CODE_STYLE.md: Code style guidelines: READ BEFORE CONTRIBUTING ANY CODEMUJOCO_CONVENTIONS.md: Definitive interpretation of MuJoCo state variables and their mapping to Ptera Software's axes, points, frames, and transformationsRUNNING_TESTS_AND_TYPE_CHECKS.md: Instructions for running tests and type checks READ BEFORE RUNNING TESTS OR TYPE CHECKS LOCALLYSTRONG_COUPLING.md: Mathematical framework for the strongly coupled free-flight UVLM-MuJoCo solver: the fixed-point sub-iteration, Aitken relaxation, the weighting matrix, and the convergence tolerancesTYPE_HINT_AND_DOCSTRING_STYLE.md: Guidelines for type hinting and docstring formatting: READ BEFORE CONTRIBUTING ANY CODE OR WRITING ANY DOCSTRINGSWRITING_STYLE.md: Guidelines for writing style in comments and documentation: READ BEFORE WRITING ANY DOCUMENTATION, DOCSTRINGS, OR COMMENTS
examples/: Directory with example scripts for userspterasoftware/: Main package with modular solver architecturegeometry/: Package with aircraft geometry classes_airfoils/: Directory containing data files with airfoil coordinates_meshing.py: Wing mesh generationairfoil.py: Airfoil class with coordinate generationairplane.py: Airplane class with coordinate transformationswing.py: Wing class with symmetry processingwing_cross_section.py: WingCrossSection class with validation
movements/: Package with movement classes (definitions for time-dependent motion)aeroelastic_airplane_movement.py: AeroelasticAirplaneMovement classaeroelastic_movement.py: AeroelasticMovement classaeroelastic_wing_cross_section_movement.py: AeroelasticWingCrossSectionMovement classaeroelastic_wing_movement.py: AeroelasticWingMovement classairplane_movement.py: AirplaneMovement classfree_flight_movement.py: FreeFlightMovement classfree_flight_operating_point_movement.py: FreeFlightOperatingPointMovement classmovement.py: Movement classoperating_point_movement.py: OperatingPointMovement classwing_cross_section_movement.py: WingCrossSectionMovement classwing_movement.py: WingMovement class
_colormap_data/: Directory containing data files with the vendored color map and color palette colors, along with their licenses_aerodynamics_functions.py: Induced velocity functions_colormaps.py: Color maps and color palettes used by the visualization functions_convergence_cache.py: JSON solve and memo cache for convergence analysis_convergence_meshing.py: Mesh building and refinement for convergence iterations_core.py: Core classes for the movement and problem hierarchies_coupled_unsteady_ring_vortex_lattice_method.py: Coupled unsteady UVLM solver subclass with step-by-step geometry_fixed_point_relaxation.py: Pure fixed-point relaxation helpers (weighted norm, convergence test, Aitken relaxation factor) for the strong-coupling sub-iteration_functions.py: Shared utility functions_logging.py: Contains function for setting up logging_mujoco_model.py: Contains the MuJoCoModel class._oscillation.py: Oscillation functions for movement classes_output_plotting.py: Matplotlib figure drawing for the visualization functions_output_rendering.py: PyVista styling, geometry building, and scene assembly for the visualization functions_panel.py: Panel class for discretized mesh elements_parameter_validation.py: Input validation functions_private_access.py: Registration pattern that grants cross-module access to private attributes, currently a FreeFlightUnsteadyProblem's MuJoCoModel for the rendering layer_serialization.py: JSON serialization and deserialization (save/load)_transformations.py: Coordinate transformations and rotationsaeroelastic_unsteady_ring_vortex_lattice_method.py: Aeroelastic UVLM solver subclass with first-order structural deformationconvergence.py: Convergence analysis toolsfree_flight_unsteady_ring_vortex_lattice_method.py: Free flight UVLM solver subclass with six-DOF MuJoCo couplingoperating_point.py: OperatingPoint classoutput.py: Visualization and results processingproblems.py: SteadyProblem and UnsteadyProblem classessteady_horseshoe_vortex_lattice_method.py: Steady horseshoe VLM solversteady_ring_vortex_lattice_method.py: Steady ring VLM solvertrim.py: Trim analysis functionalityunsteady_ring_vortex_lattice_method.py: Unsteady ring UVLM solver
scripts/: Directory with maintenance and tooling scriptshero_generation/: Scripts for creating and finalizing the README hero graphiccreate_solve_and_save_hero.py: Creates, solves, and saves the hero simulationfinalize_and_save_hero.py: Renames preview hero graphics to their permanent namesload_and_visualize_hero.py: Loads the saved hero simulation and generates preview graphics
analyze_webp.py: Renders WebP frames to PNG files for inspection (backs theanalyze-webpslash command)check_ascii_only.py: Pre-commit hook script that flags non-ASCII characters in text filescheck_pinned_versions.py: Pre-commit hook script that verifies the active environment holds the exact versions pinned inrequirements_dev.txtfind_unused_fixtures.py: Finds and optionally deletes unused fixtures and deadsetUpattributes across the test suite (backs thedelete-unused-fixturesslash command)regenerate_example_outputs.py: Runs all example scripts (or a single named example) and collects their outputs intodocs/examples_expected_output/, re-rendering oversized WebP files at lower quality
tests/: Directory with unit and integration testsintegration/: Integration tests for combined functionality, with shared fixtures in afixtures/subpackage. There is one test module per solver configuration worth exercising end-to-end (each solver, plus its surface-effect, wake-truncation, multiple-wing, and variable-geometry variants), along with modules for convergence, trim, output, and serialized outputunit/: Unit tests for individual classes and functions, with shared fixtures in afixtures/subpackage. The test modules mirror the package's modules one-to-one (for example,test_wing.pytestsgeometry/wing.py), plus a few suite-level modules such astest_package_init.py,test_slots.py, andtest_test_environment.py. Fixture modules are named after the test modules they serve_test_environment.py: Configures the test process to quiet known sources of test run noise (the serialization dirty-tree warnings, tqdm progress bars, and the headless-Linux VTK warning). It is imported as the first line oftests/__init__.pyso the suppressions are in place before any pterasoftware, pyvista, or tqdm module loads
validation/: Directory with the experimental validation study:validation_study.pysimulates a flapping test stand from Yeo et al., 2011 and compares the UVLM results against the paper's published pressure measurements, which are stored alongside it as CSV files extracted from the paper, along with the accompanying report (validation_paper.pdf).codespell-ignore.txt: File listing words to ignore in spell checking.gitignore: Git ignore file.pre-commit-config.yaml: Pre-commit configuration file.readthedocs.yaml: Read the Docs build configurationCITATION.cff: Citation metadata for the project (powers GitHub's cite-this-repository feature and the Zenodo release record)codecov.yml: Codecov configuration for test coverage reportingCONTRIBUTING.md: Contribution guidelines for developersMANIFEST.in: Manifest file for packagingmypy.ini: MyPy configuration filepyproject.toml: Project configuration fileREADME.md: Project overview and installation instructions for developersrequirements.txt: Full list of runtime dependencies with version constraintsrequirements_dev.txt: Full list of development dependencies with version constraintsrequirements_min.txt: Minimum-version runtime dependenciessetup.cfg: Setup configuration file
The project's .claude/settings.json restricts which shell commands Claude Code may run. For git specifically, the subcommands fall into three tiers:
- Denied (cannot run at all):
git am,git apply,git bisect,git branch,git cherry-pick,git clean,git clone,git config,git fetch,git init,git lfs,git merge,git mv,git pull,git push,git rebase,git remote,git reset,git revert,git rm,git sparse-checkout,git stash,git submodule,git switch,git tag, andgit worktree. - Ask (prompt for approval each time):
git add,git checkout,git commit, andgit restore. - Allowed (run without a prompt):
git diff,git grep,git log,git ls-files,git show, andgit status.
The practical consequences are worth internalizing before planning any git workflow:
git pushis denied, so Claude cannot push. When a workflow needs the branch on the remote (for example, before opening a pull request), the user must push it manually.git branchis denied even for read-only listing, so usegit statusorgit logto determine the current branch instead.- A compound command fails if any single part is denied. For example,
git branch --show-current && git statusis rejected becausegit branchis denied, even thoughgit statuson its own is allowed. Split such commands into separately allowed invocations.
- Forgetting to read RUNNING_TESTS_AND_TYPE_CHECKS.md before running tests and trying to use pytest (Ptera Software uses unittest)
- Forgetting to read CODE_STYLE.md before contributing code
- Forgetting to read TYPE_HINT_AND_DOCSTRING_STYLE.md before writing docstrings
- Forgetting to read ANGLE_VECTORS_AND_TRANSFORMATIONS.md and AXES_POINTS_AND_FRAMES.md before working with vector-valued variables. If in doubt, before writing code, read both of these documents
- Forgetting to read WRITING_STYLE.md before writing documentation, docstrings, or comments