Skip to content
Jhawk414Public
forked from OpenMDAO/pyCycle

About

GE F404 turbofan cycle deck — design-point sizing and altitude/Mach/dTs off-design sweeps, built on OpenMDAO's pyCycle.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

 
 

Latest commit

 

History

513 Commits

Folders and files

Repository files navigation

Status: In Development Last Commit Open Issues

F404

A GE F404 twin-spool, low-bypass, mixed-flow, afterburning turbofan cycle model with design-point sizing and off-design flight sweeps, built on NASA Glenn's pyCycle and OpenMDAO.

Given a target thrust and component parameters (fan and HPC pressure ratios, component efficiencies, cooling bleed fractions), the model sizes the engine at sea-level-static conditions and sweeps altitude, ambient temperature offset, and throttle to generate a converged off-design performance deck.

Status: In development. One sized engine, with DESIGN at sea-level-static dry mil power, operated both dry (military power and below) and wet (afterburning) on two off-design points of the same model. Also: altitude/dTs/throttle sweep infrastructure, and an f404 command line for sweeps and single design points. See Current status for convergence coverage and Roadmap for planned work. Not yet validated against public F404 performance data; the public reports are archived and indexed in docs/unclassified_perf_data/.

Table of contents

Repo layout

F404 application code lives under src/f404/, separate from the vendored upstream pycycle library at the repo root (see #4).

Path Role
src/f404/engine_model.py MixedFlowTurbofan(pyc.Cycle): single-point thermodynamic cycle (fan, HPC, burner, HPT/LPT, mixer, afterburner, nozzle)
src/f404/mp_cycle.py MPMixedFlowTurbofan(pyc.MPCycle): one DESIGN point (dry mil) feeding two off-design points, OD_dry and OD_wet, with map scalars and station areas
src/f404/problems.py build_problem(): design targets, the max-AB calibration, initial guesses and input validation
src/f404/sweep_utils.py Sweep infrastructure: snake-pattern sweep grid, bridge-point warm-starting, SweepRunner, result extraction
src/f404/cli.py f404 command line: sweep and design subcommands, min,max,step range parsing and validation
src/f404/sweep_full_envelope.py Sweep driver: default grid, run_sweeps() for dry, wet, or both modes, and the cycle-deck CSV writer
src/f404/printer.py Console table formatter for DESIGN/OD results
tests/ pytest suite, one <module>_test.py per module (#5)
deck/ Cycle-deck output CSVs
docs/ System architecture diagrams (f404_cycle.typ, f404_cycle.svg), architecture decision records (adr/), planning docs (improvements/), and reference material (unclassified_perf_data/: an index and cross-study reference map of published F404 performance data, with source PDFs in pdf/ and Obsidian-compatible markdown conversions with their figures in md/)
AGENTS/ Session handoff notes
meta/ Vendored-library provenance (LICENSE.txt)
pycycle/, setup.py, pyproject.toml, example_cycles/ Vendored upstream pyCycle library

Cycle architecture

The thermodynamic cycle model in engine_model.py (MixedFlowTurbofan) represents the twin-spool, mixed-flow, augmented F404 turbofan engine:

F404 Turbofan Cycle Architecture

Diagram source maintained in docs/f404_cycle.typ.

Key cycle components and mechanical couplings:

  • Low Pressure (LP) Spool: 3-stage fan driven by the single-stage LP turbine via lp_shaft (10,000 rpm).
  • High Pressure (HP) Spool: 7-stage HP compressor driven by the single-stage HP turbine via hp_shaft (14,000 rpm, 250 hp customer power extraction).
  • Cooling Bleeds: HPC interstage bleed (cool1, 5.07% flow) cools the LPT; compressor discharge bleed (cool3, 11.0% flow) cools the HPT.
  • Mixed Exhaust & Augmentor: Core flow and bypass flow mix in a confluent mixer, then pass through the afterburner duct and expand through a variable convergent-divergent nozzle (mixed_nozz). The afterburner is an active combustor in wet mode, with a 5.4% hot pressure loss, and a lossless pass-through in dry mode.
  • One engine, two modes: the engine is sized once, at SLS dry mil (11,000 lbf, Tt4 3100 R). Dry points run the DESIGN nozzle throat (A8). Wet points open A8 to hold the fan on its design operating line, so lighting the afterburner leaves the gas generator where dry mil put it. Max AB is Tt7 3608 R, calibrated to 17,700 lbf SLS. See ADR-0001 for the trade study behind this.

Software architecture and data flow

Current data flow from CLI invocation to output CSV.

flowchart TD
    subgraph Drivers["Entry point (src/f404/)"]
        CLI["cli.py  (f404)<br/>sweep · design<br/>--mode · --alt · --dts · --throttle · --out"]
        A["sweep_full_envelope.py<br/>run_sweeps · write_deck_csv"]
    end

    subgraph Model["Cycle model"]
        B["problems.py<br/>build_problem<br/>targets, calibration, guesses, validation"]
        C["mp_cycle.py<br/>MPMixedFlowTurbofan(pyc.MPCycle)<br/>wires DESIGN + OD_dry + OD_wet"]
        D["engine_model.py<br/>MixedFlowTurbofan(pyc.Cycle)<br/>single-point thermodynamic cycle"]
    end

    subgraph Sweep["Sweep infrastructure"]
        E["sweep_utils.py<br/>build_snake_sweep · generate_bridge_points<br/>SweepRunner · extract_od_results"]
    end

    subgraph Output["Output"]
        F["printer.py<br/>page_viewer() console tables"]
        G["deck/*.csv<br/>cycle_deck_dry / _wet / _full_envelope"]
    end

    CLI --> A
    CLI --> B
    A --> B
    B --> C
    C --> D
    B --> F
    A --> E
    E --> C
    E --> G
Loading

mp_cycle.py instantiates MixedFlowTurbofan three times:

  • with design=True: the DESIGN point, solved once to size the engine;
  • with design=False and afterburn=False: OD_dry;
  • with design=False and afterburn=True: OD_wet.

It passes converged map scalars and station areas from DESIGN into both OD points, so off-design calculations use the one sized engine geometry. A sweep re-solves the OD point for its mode at each condition and freezes the other.

Installation

This repository vendors OpenMDAO's pyCycle library. Install in editable mode from a local clone:

git clone git@github.com:Jhawk414/F404.git
cd F404
pip install -e .[all]

Requires Python 3.9+ and OpenMDAO 3.10.0+.

Usage

pip install -e .[all] installs an f404 command (re-run it in an existing checkout to pick up the entry point). python -m f404 is equivalent and needs no install beyond the package being importable.

f404 sweep                      # dry + wet, default grid, decks in the cwd
f404 sweep --mode wet           # one mode only
f404 sweep --alt 0 --dts -20,20,10   # one altitude, a dTs range
f404 design                     # solve and print DESIGN, OD_dry and OD_wet
f404 --help                     # and `f404 sweep --help`, `f404 design --help`
                                # (rich panels; plain argparse text for usage errors)

f404 sweep

Sweeps the sized engine over altitude, temperature offset and throttle, and writes cycle_deck_dry.csv / cycle_deck_wet.csv (plus cycle_deck_full_envelope.csv for --mode both). With no range flags the grid is the default one below, so the output matches earlier decks.

Flag Meaning Default
--mode {dry,wet,both} afterburner mode both
--alt MIN,MAX,STEP altitude, ft 0,5000,2500
--dts MIN,MAX,STEP ISA temperature offset, R -50,50,10
--throttle MIN,MAX,STEP Tt4 (dry) or Tt7 (wet), R 2500,3100,200 dry, 3008,3608,200 wet
--out DIR deck directory, created if missing .
# Wet sweep: T7 from 3608 down to 3008 R (Tt4 held at mil, 3100 R)
f404 sweep --mode wet --alt 0,10000,2500 --dts 0,20,10 \
           --throttle 3008,3608,200 --out /tmp/run1

--throttle is shown here at its wet default for completeness; leave it off to get the same T7 values.

  • Each range is one min,max,step triple, inclusive of max, bare or bracketed (--alt [0,10000,1000]). The order is fixed.
  • A single value holds the axis constant (--alt 0, --throttle 3100). Step 0 is not a constant axis; it is an error.
  • A range may start with a negative number (--dts -20,20,10). main() joins it to its flag before argparse, which would otherwise read it as a flag (#22).
  • Axes are walked in the order the solver's warm-starting expects, whatever the flag order: --dts hot side first (0, +10 … then −10 …), --throttle high power to low.
  • --throttle needs --mode dry or --mode wet: it is a different temperature in each.
  • There is no --mach yet; Mach is pinned at 0.001 until a Mach sweep dimension exists in sweep_utils.py (#13).

A malformed flag stops the run before any model is built, with a message naming the problem: a range that isn't exactly three finite numbers, a non-positive step, min above max, a step that doesn't divide max − min evenly (so the sweep would silently stop short of max), an unusable --throttle or --out. Exit status 2 for bad arguments.

f404 design

Sizes the engine and prints the DESIGN, OD_dry (mil) and OD_wet (max AB) result tables at sea-level static, without sweeping. There is one engine, so there is no --mode. Three flags override the targets:

  • --fn-target: dry mil sizing thrust.
  • --mil-tt4: core burner exit temperature.
  • --max-tt7: max-AB afterburner exit temperature.

A non-converging solve exits 1 with the solver's message.

python -m f404.sweep_full_envelope [--mode ...] still works and is the same as f404 sweep.

Testing

pytest tests                    # full suite, ~2 min
pytest tests -m "not slow"      # structural and unit tests only, ~7 s

One tests/<module>_test.py per module (#5). Tests marked slow build and solve a full om.Problem; the rest either use pure functions or build a model without solving it. pytest needs no prior install — pythonpath in pyproject.toml puts src/ on the path.

CI (#31): a PR runs only the fast tests (-m "not slow", Ubuntu 3.12, about a minute). The full suite on Ubuntu (3.9, 3.12) and macOS (3.12) runs on every push to main, on manual dispatch, and on a PR carrying the full-ci label. Apply that label when the PR is about to merge: the golden baselines and convergence regressions are all slow.

190 tests (155 fast), 97% coverage. The driver and CLI are importable and covered; what remains uncovered is mostly sweep_utils.py's solver-failure paths and the one-line __main__ shims.

Current status

Latest full-envelope sweep (--mode both, OpenMDAO 3.39.0) at alt ∈ {0, 2500, 5000} ft, dTs ∈ {0, ±10, ±20, ±30, ±40, ±50} R, static (MN ≈ 0.001), 4 throttle levels per mode, all on the one sized engine:

Mode Converged Throttle sweep
Dry 118 / 132 Tt4 3100 → 2500 R
Wet 100 / 132 Tt7 3608 → 3008 R (Tt4 fixed at 3100 R MIL)

Decks: deck/cycle_deck_dry.csv, deck/cycle_deck_wet.csv.

Where the failures are, tracked in issue #3:

  • Wet: every point with dTs ≥ 0 R converges; all failures are on the cold (dTs < 0 R) side, worst at altitude.

  • Dry: 67 of the 72 non-cold points converge. Five hot-day, low-power points fail at Tt4 = 2500 R: dTs +40 and +50 R at 0 and 2500 ft, and +50 R at 5000 ft. The rest of the dry failures are on the cold side.

  • Wet rose from 89/132 when the wet A8 stopped being frozen at its DESIGN value (ADR-0001).

  • Dry has measured 118/132 on every run since PR #19, including a clean reinstall. The 125/132 in earlier notes is not reproducible on the current OpenMDAO.

Roadmap

Done:

  • Modular cycle model (engine_model.py / mp_cycle.py), refactored off the original monolithic MFTF_od_CRZ.py
  • Full alt/dTs/throttle sweep infrastructure with bridge-point warm-starting (sweep_utils.py)
  • Dry (MIL) / wet (max-AB) mode split, with convergence-detection bugs fixed (bound-saturated states no longer reported as converged)
  • Repo-root cleanup: removed the superseded MFTF_od_CRZ.py monolith and unused vendor/CI cruft (release_notes.md, .travis.yml, .bumpversion.cfg), moved reference PDFs into docs/unclassified_perf_data/
  • Cap cycle-deck CSV precision — single write_deck_csv() writer with per-column decimals (scientific %.4e for the fuel-air ratios) (#12)
  • Per-module test suite (tests/<module>_test.py), 87% coverage, with golden DESIGN/OD baselines and regression cover on the false-convergence guards (#5)
  • Single-engine sizing: one DESIGN at dry mil feeding dry and wet OD points, wet A8 control law, max AB calibrated to 17,700 lbf (#2, ADR-0001)
  • src/ restructure: F404 app code separated from the vendored pyCycle library, now the f404 package under src/f404/ (#4)
  • Vendored pycycle/ synced against upstream (#6)
  • f404 CLI with sweep and design and --alt / --dts / --throttle range flags; single-value constant axes (#24) and negative-start ranges (#22)
  • CI: fast tests on PRs, full matrix on merge or the full-ci label (#31)
  • Published F404 performance reports archived as Obsidian-compatible markdown, with an index and cross-study reference map (docs/unclassified_perf_data/)

Planned (see docs/improvements/IMPROVEMENTS.md for full detail), roughly in order:

  • CLI sweep-axis follow-ups: --mach (needs a Mach sweep dimension, #13) and a PLA axis (needs PLA defined in the cycle first, #30)
  • Write failed sweep points to deck/ beside each cycle deck (#27)
  • Pydantic models for design-point inputs, sweep points and the duplicated OD bounds table (#17)
  • PLA/T7-scheduled nozzle throat area (#8), together with defining idle and calibrating the dry part-power end against the published data (#25)
  • Resolve remaining cold/high-alt/max-AB Newton convergence failures (#3)
  • CLI init-config and YAML configuration (#16)
  • Inline creep/LCF life estimation (#10)
  • deck/ as a durable, reviewed home for cycle-deck CSVs + solver logs
  • YAML-driven run configuration (run.yml), on top of #17's models
  • Auto-generated sweep-envelope coverage plot

Acknowledgments

This repo is a fork of NASA Glenn's pyCycle (om-pycycle on PyPI), built on the OpenMDAO framework. The pycycle/ library code, setup.py, and example_cycles/ are vendored upstream scaffolding, not F404-specific.

If you use pyCycle itself, please cite:

E. S. Hendricks and J. S. Gray, "pyCycle: A Tool for Efficient Optimization of Gas Turbine Engine Cycles," Aerospace, vol. 6, iss. 87, 2019. doi:10.3390/aerospace6080087

License

Apache License 2.0. See meta/LICENSE.txt.

About

GE F404 turbofan cycle deck — design-point sizing and altitude/Mach/dTs off-design sweeps, built on OpenMDAO's pyCycle.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages