|
STAR
Cal STAR — firmware, DAQ server, and engine design
|
Classes | |
| class | StartLine |
| class | StartChamber |
| class | StartSettings |
| class | Element |
| class | FeedLine |
Functions | |
| Dict[str, Any] | inp (Any value, str unit, str provenance) |
| Dict[str, Any] | model_block (str name, str source, Sequence[str] assumptions, Mapping[str, Dict[str, Any]] inputs) |
| Dict[str, Any] | unavailable (str error) |
| Optional[float] | finite (Any x) |
| str | param_provenance (Any param, str note="") |
| float | column_step (float m, float dp, float inertance, float resistance, float dt) |
| float | chamber_step (float pc, float mdot_in, float rt_over_v, float at_over_cstar, float dt) |
| float | gamma_function (float gamma) |
| float | linear_characteristic (float x) |
| float | _interp_time (float t0, float dt, float v0, float v1, float target) |
| Dict[str, Any] | run_start (StartLine ox, StartLine fuel, StartChamber chamber, *, float dt=1.0e-5, float horizon_s=0.25, float settle_tol=0.01, float record_every_s=5.0e-4) |
| Tuple[float, int] | _call (Callable[[float, float], float] fn, float a, float b) |
| Optional[float] | _settle_time (List[Tuple[float, float, float, float]] trace, Tuple[float, float] m_end, float F_end, float tol, float t_ign) |
| Dict[str, float] | fixed_load_deficit (*, Sequence[Tuple[float, float, float, float]] trace, float t_window, float F_settled, Tuple[float, float] mdot_settled, float scale_F=1.0, Tuple[float, float] scale_m=(1.0, 1.0), float c_end, float mr_end, Tuple[float, float] residual_extra) |
| List[str] | feed_path (Any net, str inlet, str tank) |
| Dict[str, Dict[str, Any]] | _params_inputs (str prefix, Any comp, Sequence[str] names, Mapping[str, str] notes={}) |
| FeedLine | feed_line (Any prep, str side, *, float mdot_ref, float p_ref, float T_ref) |
| Tuple[float, bool] | exit_area (FeedLine feed) |
| Dict[str, Dict[str, Any]] | manifold_volumes (Any config) |
| int | _first_firing (Mapping[str, Any] series) |
| int | _last_firing (Mapping[str, Any] series) |
| Callable[[float, float], Tuple[float, bool]] | _card_fn (Any table, str label) |
| Dict[str, Any] | settled_point (Mapping[str, Any] result) |
| Dict[str, Any] | start_from_run (Any prep, Mapping[str, Any] result, Any config=None, StartSettings settings=StartSettings()) |
| Dict[str, Any] | _start_from_run (Any prep, Mapping[str, Any] result, Any config, StartSettings settings) |
Variables | |
| float | PSI = 6894.757293168361 |
| float | G0 = 9.80665 |
| tuple | SIDES = (("oxidiser", "ox"), ("fuel", "fuel")) |
| str | MODEL_NAME = "start_transient_rigid_column" |
Layer X start transient: Fire to settled flow, as a reduced-order model of its own.
``start_from_run(prep, result, config=None, settings=StartSettings())`` -> ``diagnostics.start``
(DATA-CONTRACT 3). ``run_start(ox, fuel, chamber, ...)`` is the model on plain inputs.
The main burn does not change. The twin's network is algebraic: its first firing step is
already at full flow (AUDIT 9.5 §1, §5), so the start is a diagnostic beside the burn and a
correction estimate (the impulse the start costs), never an edit of the burn.
The model
---------
Each side is one liquid column, tank outlet to injector orifices, in lumped (rigid-column)
form, the inertance-resistance line of AUDIT 7 item 1:
I dm/dt = p_tank - p_end - R m|m| I = sum L/A [1/m], R [Pa/(kg/s)^2]
* **Valve.** The drawing's main valve opens on command as a linear travel over its drawn
``travel_time``; its Cv follows the valve's own inherent characteristic (feedtwin
``Valve.effective_cv``), and its loss is feedtwin's (``fluids`` Cv-to-K), so
``R_valve(x) = R_valve(1) (Cv(1)/Cv(x))^2``.
* **Lines.** Each element's quadratic loss is the twin's own ``pressure_drop`` (Darcy with the
drawing's friction correlation and ``K_minor``) at the main burn's first settled flow, divided
by that flow squared: the friction factor is frozen there.
* **Priming.** Downstream of the main valve the line, the injector manifold and the orifices are
gas-filled at Fire (AUDIT 9.5 §4: the twin holds them liquid at 101 kPa, which would flash).
The liquid front fills that volume; the gas it displaces vents through the orifices into the
chamber. While it fills, the column's inertance grows with the length of downstream tube it
occupies, its end pressure is the chamber's (ambient before ignition: the displaced gas's
orifice drop, ``rho_g/2 (Q/A_orifices)^2``, is under 7 kPa at LE4's arrival flows against ~3.9 MPa of
drive, and is neglected), and the liquid
entering the gas volume loses ``K_exit_prime`` velocity heads at the last drawn tube's bore (1: the
"1" of Liou & Hunt's ``(1 + K)``, the velocity head the growing column carries, which is also the
Borda dump of a front entering a larger volume; their entrance ``K`` is the drawing's tank-exit
``K_minor``, already in the line loss). This is the
rigid-column filling model: the unsteady Bernoulli/momentum balance on a column of growing
length entering from a reservoir, ``rho l dv/dt = p_res - p_front - (1 + K) rho v^2/2 - f l rho v^2/(2D)``
(Liou & Hunt, "Filling of pipelines with undulating elevation profiles", J. Hydraul. Eng.
122(10), 1996, rigid-column model). Once the manifold is full the injector's capacity takes
over: ``m = phi sqrt(p_line_exit - Pc)`` (the engine card's capacity, which owns the dump and
the orifices, engine/layerx/card.py), and the orifice passages add their inertance.
* **Ignition** is when both manifolds are primed, plus ``ignition_delay_s`` (an explicit input:
0 = the igniter is lit and propellant ignites on arrival). Before it the chamber is at
ambient (cold flow through the throat costs ~1 kPa).
* **Chamber filling** after ignition: ``dPc/dt = (R T / V)(m_in - Pc A_t / c*)`` with
``R T = (Gamma c*)^2`` (the ideal-rocket identity c* = sqrt(R T)/Gamma, Sutton & Biblarz,
Rocket Propulsion Elements, the characteristic-velocity relation), c* from the engine card at the instantaneous O/F and
flow, and propellant burning on arrival (no vaporisation lag; the chug model owns that lag).
The chamber's time constant is ``L* / (Gamma^2 c*)`` (AUDIT 9.5 §1: 2.1 ms on LE4).
* **Thrust** is the card's vacuum exhaust velocity times the nozzle flow, less ``p_a A_e``,
floored at zero (a separated nozzle at low Pc is not modelled; it would give more thrust than
this, so the deficit here is the larger figure).
Integration is backward Euler on each column with the quadratic loss solved exactly (stable for
any valve opening, exact for an inertance-only line), and backward Euler on the chamber, at a
fixed ``dt`` (10 us default, 200x below the shortest line constant on LE4).
What it reports
---------------
* ``prime_ox_s``, ``prime_fuel_s``, ``ignition_s``; Pc, flows and O/F through the start.
* ``impulse_deficit_Ns``: the total impulse a burn with this start delivers less than the main
burn, at a **fixed propellant load**. The start window (Fire to settled) is credited at the
main burn's first settled thrust in the main burn (its first firing step is at full flow and
is copied back to Fire, replay.timeseries_payload); the propellant the start did not spend is
burned at the end at the main burn's end-of-burn exhaust velocity, limited by whichever tank
runs dry, so a fuel lead that eats into fuel the main burn strands costs less than its mass.
The mass that fills the downstream line and manifold is not charged: like the twin's massless
lines, it is pushed through at burnout.
* ``hard_start``: a **heuristic** (no cited criterion): propellant both sides have injected and
not yet burned at ignition, paired at the design O/F, against the chamber's own steady gas
inventory ``Pc V / (Gamma c*)^2``. Over ``hard_start_ratio`` (1.0) of it, burning that pair at
once in the chamber volume would by itself exceed the steady chamber pressure.
Limits (stated in the model block): tank pressure held at its T-0 value through the start; the
line is incompressible (the arrival surge at the orifices is reported as the rigid-column
orifice back-pressure; its compressible part is water hammer, ``diag.waterhammer``); the
manifold fills before any orifice flows; the friction factor is frozen at the settled flow; the
engine card is clipped to its table (flagged by how often).
|
protected |
``fn(a, b)``; a function that clips (an engine card table) says so through a ``(value, clipped)`` tuple, a plain function returns a float.
Definition at line 412 of file start.py.
Referenced by run_start().
|
protected |
|
protected |
Definition at line 712 of file start.py.
Referenced by settled_point().
|
protected |
|
protected |
Definition at line 719 of file start.py.
Referenced by _start_from_run().
|
protected |
Definition at line 575 of file start.py.
References finite(), inp(), and param_provenance().
Referenced by feed_line().
|
protected |
The last instant thrust or either injected flow is outside ``tol`` of its final value.
Definition at line 421 of file start.py.
Referenced by run_start().
|
protected |
Definition at line 769 of file start.py.
References _card_fn(), _last_firing(), exit_area(), feed_line(), finite(), fixed_load_deficit(), inp(), manifold_volumes(), max, min, model_block(), run_start(), and settled_point().
Referenced by start_from_run().
| float engine.layerx.diag.start.chamber_step | ( | float | pc, |
| float | mdot_in, | ||
| float | rt_over_v, | ||
| float | at_over_cstar, | ||
| float | dt ) |
One backward-Euler step of ``dPc/dt = (RT/V)(m_in - Pc A_t/c*)``.
Definition at line 156 of file start.py.
Referenced by run_start().
| float engine.layerx.diag.start.column_step | ( | float | m, |
| float | dp, | ||
| float | inertance, | ||
| float | resistance, | ||
| float | dt ) |
One backward-Euler step of ``I dm/dt = dp - R m|m|``, the quadratic solved exactly. ``I (m' - m)/dt = dp - R m'|m'|``. Unconditionally stable for ``R >= 0`` (a nearly shut valve is a huge R and a tiny time constant ``I/(2 R m)``), and exact when ``R = 0``. With no inertance it is the quasi-steady ``m = sign(dp) sqrt(|dp|/R)``.
Definition at line 135 of file start.py.
Referenced by run_start().
| Tuple[float, bool] engine.layerx.diag.start.exit_area | ( | FeedLine | feed | ) |
The area the flow enters the injector manifold through [m^2], and whether it is the main valve's own bore: the last drawn line below the main valve, else the last above it, else -- a side drawn with no line at all, as LE4's LOX side is (tank outlet, OM-R, injector) -- the valve's bore. That last case used to index an empty list, and the whole start went missing from the run. With neither a line nor a valve bore on the drawing there is nothing to take it from: it raises.
Definition at line 656 of file start.py.
Referenced by _start_from_run().
| FeedLine engine.layerx.diag.start.feed_line | ( | Any | prep, |
| str | side, | ||
| * | , | ||
| float | mdot_ref, | ||
| float | p_ref, | ||
| float | T_ref ) |
The drawn feed path of ``side`` with each element's loss priced by the twin's own component at ``mdot_ref`` and the fluid's state at ``p_ref`` [Pa], ``T_ref`` [K].
Definition at line 587 of file start.py.
References _params_inputs(), feed_path(), and max.
Referenced by _start_from_run().
| List[str] engine.layerx.diag.start.feed_path | ( | Any | net, |
| str | inlet, | ||
| str | tank ) |
Branch ids from the tank down to the injector inlet (a breadth-first walk upstream, so a fill or vent tee meeting the path is not taken for the feed). Same walk as engine/layerx/flight.py ``_path_to_tank``.
Definition at line 493 of file start.py.
Referenced by feed_line().
| Optional[float] engine.layerx.diag.start.finite | ( | Any | x | ) |
Definition at line 114 of file start.py.
Referenced by _params_inputs(), and _start_from_run().
| Dict[str, float] engine.layerx.diag.start.fixed_load_deficit | ( | * | , |
| Sequence[Tuple[float, float, float, float]] | trace, | ||
| float | t_window, | ||
| float | F_settled, | ||
| Tuple[float, float] | mdot_settled, | ||
| float | scale_F = 1.0, | ||
| Tuple[float, float] | scale_m = (1.0, 1.0), | ||
| float | c_end, | ||
| float | mr_end, | ||
| Tuple[float, float] | residual_extra ) |
Total impulse lost to the start at a fixed propellant load [N s].
The main burn credits ``F_settled`` from Fire to ``t_window`` and spends ``mdot_settled``
per side over it. The start delivers ``J_s`` and spends ``m_s`` (injected) over the same
window. After the window the two burns are the same burn, except at the end: the real one
has ``E = (mdot_settled t_w - m_s) + residual_extra`` more of each propellant than the main
burn had when it ended, burned at O/F ``mr_end`` until the first side runs out, at
``c_end`` [m/s]. ``residual_extra`` is each side's main-burn residual over the dry mass.
deficit = (F_settled t_w - J_s) - c_end * min(E_ox, mr_end E_fu) (1 + 1/mr_end)
``trace`` is ``(t, F, m_ox_injected, m_fuel_injected)`` at a fixed step from the start's
first valve command; ``scale_*`` put the model's own steady state on the main burn's scale.
Definition at line 437 of file start.py.
Referenced by _start_from_run().
| float engine.layerx.diag.start.gamma_function | ( | float | gamma | ) |
Vandenkerckhove's Gamma = sqrt(g) (2/(g+1))^((g+1)/(2(g-1))); the ideal-rocket mass-flow function (Sutton & Biblarz, Rocket Propulsion Elements).
Definition at line 162 of file start.py.
Referenced by run_start().
| Dict[str, Any] engine.layerx.diag.start.inp | ( | Any | value, |
| str | unit, | ||
| str | provenance ) |
One entry of a model block's ``inputs`` (DATA-CONTRACT).
Definition at line 96 of file start.py.
Referenced by _params_inputs(), _start_from_run(), and manifold_volumes().
| float engine.layerx.diag.start.linear_characteristic | ( | float | x | ) |
| Dict[str, Dict[str, Any]] engine.layerx.diag.start.manifold_volumes | ( | Any | config | ) |
Each side's injector volume downstream of its feed port, from the config's injector layout (engine/core/injectors/layout.py): the ring channel (cross-section x 2 pi r_center) and the orifice passages (n x pi/4 d^2 x through-length). Returns per ``ox``/``fuel``: ``V_m3``, ``I_inj`` (passage length over total passage area) and the inputs. The plate's feed ports and any back-cover passages are not in the layout and are not counted.
Definition at line 672 of file start.py.
References inp().
Referenced by _start_from_run().
| Dict[str, Any] engine.layerx.diag.start.model_block | ( | str | name, |
| str | source, | ||
| Sequence[str] | assumptions, | ||
| Mapping[str, Dict[str, Any]] | inputs ) |
DATA-CONTRACT ``model``: what produced a block, so the run record can list it.
Definition at line 103 of file start.py.
Referenced by _start_from_run().
| str engine.layerx.diag.start.param_provenance | ( | Any | param, |
| str | note = "" ) |
``"<source>: <reference>"`` for a feedtwin ``Param`` (a drawing value), plus a note.
Definition at line 122 of file start.py.
Referenced by _params_inputs().
| Dict[str, Any] engine.layerx.diag.start.run_start | ( | StartLine | ox, |
| StartLine | fuel, | ||
| StartChamber | chamber, | ||
| * | , | ||
| float | dt = 1.0e-5, | ||
| float | horizon_s = 0.25, | ||
| float | settle_tol = 0.01, | ||
| float | record_every_s = 5.0e-4 ) |
Integrate the start. Returns the time histories and the event times (SI, Pa).
Definition at line 277 of file start.py.
References _call(), _interp_time(), _settle_time(), chamber_step(), column_step(), gamma_function(), max, and min.
Referenced by _start_from_run().
| Dict[str, Any] engine.layerx.diag.start.settled_point | ( | Mapping[str, Any] | result | ) |
The main burn's first settled operating point: the delivered (replay) first point when the replay ran, else the twin's first firing step.
Definition at line 738 of file start.py.
References _first_firing().
Referenced by _start_from_run().
| Dict[str, Any] engine.layerx.diag.start.start_from_run | ( | Any | prep, |
| Mapping[str, Any] | result, | ||
| Any | config = None, | ||
| StartSettings | settings = StartSettings() ) |
``diagnostics.start`` for a finished Layer X run. Never raises.
Definition at line 760 of file start.py.
References _start_from_run(), and unavailable().
| Dict[str, Any] engine.layerx.diag.start.unavailable | ( | str | error | ) |
DATA-CONTRACT: a block that could not be computed. It never raises.
Definition at line 109 of file start.py.
Referenced by start_from_run().
| str engine.layerx.diag.start.MODEL_NAME = "start_transient_rigid_column" |