|
| None | register_propellant_alias (str name, str species) |
| str | species_for (str name) |
| None | register_injector_type (str name, AreaExtractor extractor) |
| list[str] | registered_injector_types () |
| tuple[float, float, int] | injector_areas (str injector_type, Mapping[str, object] geometry, str side) |
| float | _as_float (Mapping[str, object] block, str key, str where) |
| tuple[float, float, int] | _impinging (Mapping[str, object] geometry, str side) |
| tuple[float, float, int] | _pintle (Mapping[str, object] geometry, str side) |
| tuple[float, float, int] | _coaxial (Mapping[str, object] geometry, str side) |
What feed-twin needs from an engine design, and nothing more.
An EngineDesign Layer-1 config is a large document -- ablative cooling, spray
SMD correlations, optimizer weights, CEA cache paths, structural margins. Almost
none of that is a feed-system boundary condition. What a feed system needs to
know about the engine at its end is small and specific:
* the **effective flow area** each propellant sees at the injector face,
* the **discharge coefficient** on each side and how it moves with Reynolds,
* which **propellants** those are, so the property layer can be asked,
* the **throat area**, which converts total flow into chamber pressure,
* and the **design point** -- thrust, mixture ratio, chamber pressure -- so the
import can be checked against what Layer 1 thought it had designed.
:class:`EngineDesign` is that subset, and it is deliberately a plain record
rather than a live handle on an EngineDesign object. Two reasons. It can be
serialised into a feed-twin scenario, so a run is reproducible without the other
repo present. And it makes the coupling *explicit*: every quantity crossing the
boundary is named in one place, so nobody has to read two codebases to find out
what the engine is being told.
Injector types are not interchangeable
--------------------------------------
The area calculation is the one genuinely type-specific piece, and getting it
from the wrong formula is silent -- a wrong area is a wrong flow is a wrong
chamber pressure, and every number downstream stays plausible. So each type has
its own extractor, registered by name, and an unrecognised type is refused
rather than guessed at:
``impinging``
``n_elements`` round jets per side. ``A = n . pi d_jet^2 / 4``.
``pintle``
Oxidiser through discrete orifices, fuel through the annulus between the
pintle tip and the reservoir wall. The two sides use *different formulae*,
which is exactly the trap.
``coaxial``
Core ports and an outer annulus, same asymmetry.