ensim.core.engine#
The entry point for engine analysis: an operating point in, chamber state and performance out. See the Python API page for examples and nozzle expansion for the model.
Engine analysis in one call: chamber equilibrium, then nozzle performance.
>>> from ensim.core.engine import EngineInputs, analyze_engine
>>> result = analyze_engine(EngineInputs("RP-1", "LOX", of_ratio=2.6,
... chamber_pressure=7e6, expansion_ratio=25))
>>> round(result.vacuum.isp) # doctest: +SKIP
326
Propellants are named by the keys of :data:ensim.core.propellants.PROPELLANTS
(LH2, LOX, RP-1, NTO, ...) and enter the chamber in their storage state. Any
other name is looked up in the thermo database and treated as a gas.
The chamber composition comes from Gibbs energy minimisation. The nozzle
expands that composition frozen, with temperature-dependent heat capacity
(:mod:ensim.core.frozen_flow); this matches NASA CEA's frozen rocket problem
and slightly understates Isp compared with shifting equilibrium.
Efficiencies scale the ideal result: c* by eta_cstar, the thrust
coefficient by eta_cf, and the momentum term by the conical divergence
factor (1 + cos alpha) / 2.
EngineInputs
dataclass
#
Operating point of a bipropellant engine. SI units.
EngineResult
dataclass
#
analyze_engine #
Solve the chamber equilibrium and the nozzle for inputs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inputs
|
EngineInputs
|
Operating point. |
required |
database
|
SpeciesDatabase | None
|
Species data; the packaged NASA Glenn set by default. |
None
|
Raises:
| Type | Description |
|---|---|
KeyError
|
A propellant is not in the database. |
ConvergenceError
|
The equilibrium solver did not converge. |
ValueError
|
The operating ambient pressure is too high for choked flow. |
Building blocks#
frozen_flow #
Frozen-composition nozzle expansion with temperature-dependent heat capacity.
The chamber mixture keeps its composition and expands isentropically:
s(T, p) = s_chamber, with s and h from the NASA polynomials of every
product species. The throat is where the mass flux rho*v peaks, and the exit
pressure follows from A_e/A_t = (rho v)_t / (rho v)_e. This is NASA CEA's
"frozen" rocket problem; unlike the constant-gamma relations in
:mod:ensim.core.propulsion, it keeps the drop of cp as the gas cools.
References
Gordon & McBride, NASA RP-1311 (1994), part I, section 6.
FrozenStation
dataclass
#
Flow state at one nozzle station, per unit mass of propellant.
FrozenNozzle
dataclass
#
Ideal (loss-free) frozen expansion to one area ratio.
frozen_nozzle #
frozen_nozzle(equilibrium: EquilibriumResult, database: SpeciesDatabase, area_ratio: float) -> FrozenNozzle
Expand the chamber state of equilibrium to area_ratio with frozen composition.
frozen_profile #
frozen_profile(equilibrium: EquilibriumResult, database: SpeciesDatabase, area_ratios: ndarray, supersonic: ndarray) -> dict[str, np.ndarray]
Flow state at stations of known A/A*, subsonic or supersonic per station.
The isentrope is tabulated once on a fine temperature grid and each
station interpolated in ln(A/A*). Returns arrays pressure,
temperature, mach and velocity.
geometry #
Advanced Nozzle Geometry - Rao Bell Contour.
Implements the Rao parabolic approximation for optimum thrust bell nozzle profiles.
ChamberContour
dataclass
#
Wall of a thrust chamber from injector face to nozzle exit.
x is measured from the throat (negative upstream); r is the wall
radius. supersonic flags stations downstream of the throat.
chamber_contour #
chamber_contour(throat_area: float, expansion_ratio: float, contraction_ratio: float = 4.0, characteristic_length: float = 1.0, convergence_angle: float = 30.0, percent_bell: float = 80.0, n_points: int = 160) -> ChamberContour
Cylinder, conical convergence, throat arc and Rao bell.
The cylinder length is chosen so that the chamber volume up to the throat equals L* times the throat area. The upstream throat arc has radius 1.5 Rt (Huzel & Huang).
generate_bell_contour #
generate_bell_contour(throat_radius: float, expansion_ratio: float, theta_n: float = 35.0, theta_e: float = 8.0, percent_bell: float = 80.0, n_points: int = 100) -> NozzleContour
Generate Rao parabolic bell nozzle contour.
Uses the parabolic approximation method by G.V.R. Rao (1958).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
throat_radius
|
float
|
Throat radius (m) |
required |
expansion_ratio
|
float
|
Exit area ratio (Ae/At) |
required |
theta_n
|
float
|
Initial expansion angle at throat (degrees) |
35.0
|
theta_e
|
float
|
Exit angle (degrees) |
8.0
|
percent_bell
|
float
|
Nozzle length as percent of 15° cone |
80.0
|
n_points
|
int
|
Number of contour points |
100
|
Returns:
| Type | Description |
|---|---|
NozzleContour
|
NozzleContour with full geometry definition |
Reference
Rao, G.V.R. "Exhaust Nozzle Contour for Optimum Thrust", Jet Propulsion, Vol. 28, 1958, pp. 377-382.
analysis #
Reduced frozen-gas nozzle parameter sweeps.
EngineSweep
dataclass
#
Full engine analysis repeated over one input.
sweep_engine #
sweep_engine(inputs: EngineInputs, parameter: str, values: Sequence[float] | ndarray, progress: Callable[[float], None] | None = None, cancel: Callable[[], bool] | None = None) -> EngineSweep
Re-run :func:ensim.core.engine.analyze_engine for each value of one input.
Unlike :func:run_sweep, chamber composition and temperature are solved
again at every point, so O/F and pressure sweeps are meaningful.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inputs
|
EngineInputs
|
Baseline :class: |
required |
parameter
|
str
|
|
required |
values
|
Sequence[float] | ndarray
|
Values of the parameter. |
required |
progress
|
Callable[[float], None] | None
|
Optional |
None
|
cancel
|
Callable[[], bool] | None
|
Optional |
None
|