1"""Phase 08: an optimized Layer-1 engine on the end of the feed system.
3Point it at what the optimizer wrote and fire it::
5 from feedtwin.engine import Chamber, CEATable, load_engine, injector_legs
7 design = load_engine("configs/impinging_lox_ch4_8000N_optimal.yaml")
9 # impinging injector, oxygen/methane, A_t 1398.2 mm^2,
10 # A_inj ox 124.55 mm^2 / fuel 60.76 mm^2, design 8000 N at 24.1 bar
12 chamber = Chamber(design.throat_area,
13 CEATable("output/cache/cea_cache_LOX_CH4_3D.npz",
14 expansion_ratio=design.expansion_ratio))
15 ox_leg, fuel_leg = injector_legs(design)
17Nothing is retyped. The injector areas come from Layer 1's own geometry through
18a **type-aware** extractor -- round jets for an impinging face, orifices and an
19annulus for a pintle, core and annulus for a coaxial -- and an unrecognised type
20is refused rather than guessed at, because a wrong area is a wrong mass flow and
21every number downstream of it stays perfectly plausible.
23Combustion is **propellant-aware** for real: :class:`CEATable` reads
24EngineDesign's own CEA cache, so ``c*``, chamber temperature, ``gamma`` and
25``C_F`` come from the same table both tools use. That is what lets a firing
26trace report chamber temperature and O/F drift rather than assuming them.
28The engine is a boundary, not a component: chamber pressure depends on the flows
29and the flows depend on chamber pressure, and the session closes that loop around
30the whole feed system (``feedtwin.session.core.Session._close_chamber``).
33from __future__
import annotations
66 register_injector_type,
67 register_propellant_alias,
68 registered_injector_types,
101 "engine_from_config",
106 "register_injector_type",
107 "register_propellant_alias",
108 "registered_injector_types",