STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
engine.layerx.diag.stability Namespace Reference

Functions

Optional[float] _num (Any v)
Dict[str, Any] _param_record (Any param, Optional[float] si, str unit, str fallback)
Any _runner (Any prep, Any config)
Dict[str, Dict[str, Any]] drawing_feed (Any prep)
Dict[str, Any] _line_record (str rid, str did, Optional[float] L, Optional[float] d, Any edge, Any length_param, Any bore_param, Any elevation=None)
Optional[Dict[str, np.ndarray]] _replay_geometry (Dict[str, Any] rp, Any design)
Optional[Dict[str, float]] _geometry_at (Optional[Dict[str, np.ndarray]] geo, float t, Optional[int] k)
Any _with_geometry (Any config, Optional[Dict[str, float]] g)
List[Any] _shift (Sequence[Any] streams, float dtau)
Dict[str, Any] _gate (Dict[str, Any] inp)
Dict[str, Any] _nyquist (Dict[str, Any] inp, Dict[str, Any] gate, float t)
Dict[str, Any] _tau_sweep (Dict[str, Any] inp, int n=TAU_SWEEP_POINTS)
Tuple[float, float, str] _coolprop_liquid (str fluid, float T, float p)
float korteweg (float a0, float rho, float bore, float wall, float E)
Optional[str] _wall_copied (Any prep)
Dict[str, Any] acoustics (Any prep, Dict[str, Any] series, Dict[str, Dict[str, Any]] feed_path, int i, Sequence[float] f_chug, float E=TUBE_MODULUS_PA)
Tuple[float, Dict[str, Any]] _solve_point (Any runner, Any cfg_now, float p_o, float p_f)
Dict[str, Any] _inputs (Any stab_config, float Pc, Dict[str, Any] diag, Optional[Dict[str, Any]] feed=None)
Dict[str, Any] _step_point (Dict[str, Any] series, int i)
Dict[str, Any] start_window_of (Any prep, Dict[str, Any] result, Dict[str, Dict[str, Any]] feed_path, Any start_window="auto", float settle_tau=SETTLE_TAU)
Tuple[Dict[str, Dict[str, float]], List[str]] _drawing_feed_at (Dict[str, Dict[str, Any]] feed_path, Dict[str, Any] series, Optional[int] i, Dict[str, Any] diag)
Dict[str, Any] stability_block (Any prep, Dict[str, Any] result, Any config=None, str basis="config", bool eroded=False, Any start_window="auto", *, float settle_tau=SETTLE_TAU, float tube_modulus=TUBE_MODULUS_PA)
Dict[str, Any] _block (Any prep, Dict[str, Any] result, Any config, str basis, bool eroded, Any start_window, float settle_tau, float tube_modulus=TUBE_MODULUS_PA)
Dict[str, Any] _model (str basis, bool eroded, Dict[str, Any] win, Dict[str, Any] pick, Dict[str, Dict[str, Any]] feed_path, Dict[str, Any] ac, float E)
List[Dict[str, Any]] _unmeasured (Dict[str, Any] pick, Dict[str, Dict[str, Any]] feed_path, Dict[str, Any] win, float E)
Optional[Dict[str, Any]] _check (List[Dict[str, Any]] rows, Dict[str, Any] rp, bool eroded)
Dict[str, Any] _feed_summary (Dict[str, Dict[str, Any]] feed_path, Dict[str, Any] r0)

Variables

float PSI = 6894.757293168361
float SETTLE_TAU = 3.0
int START_POINTS_MAX = 24
int TAU_SWEEP_POINTS = 41
tuple NYQUIST_HZ = (2.0, 2000.0, 400)
float NEAR_CHUG = 0.20
tuple SIDES = (("oxidiser", "oxidizer", "O", "ox"), ("fuel", "fuel", "F", "fuel"))
float TUBE_MODULUS_PA = 193.0e9
tuple TUBE_MODULUS_SOURCE
tuple SOURCE

Detailed Description

Chug margin over the burn, on the drawing's feed impedance: ``diagnostics.stability``.

DATA-CONTRACT section 3, ``stability``. Layer X audit D7 and appendix 9.4.

What Layer X's replay reports today (the ``config`` basis) is EngineDesign's chug gate at 28
replay points: the Nyquist gain margin of the lumped feed / injector / chamber loop with a double
time lag (Leonardi et al. 2017), taken at the worst point of the unmeasured mixing-lag band. Three
of its inputs do not come from the stand that is burning (audit 9.4 sections 1-3):

* the feed **inertance** is ``feed_system.<side>.length / A_hydraulic`` from the engine config,
  not the drawing's lines;
* the feed **resistance** is the Borda exit dump alone, because the replay runs on the line-exit
  copy of the config (``engine/layerx/card.py``), which zeroes K0;
* **A_t and L*** are the design point's, while the chamber erodes.

This module re-evaluates the same loop at the same points and offers the drawing's basis:

``basis="drawing"`` (D7 B+C)
    I = sum of L/A over the drawing's lines from the tank outlet to the injector inlet (the
    assembled network's path, each line's own bore); R = 2 dp/mdot with dp = the twin's own
    tank-outlet -> line-exit drop at that instant, plus the Borda dump EngineDesign prices at the
    line exit (the same dump the config basis carries). A side whose drawing declares no line, or
    a run with no outlet pressures, keeps the config's value for that side and says so: turned on
    against a drawing that declares nothing, the basis changes nothing.
``eroded=True`` (D7 D)
    The stability call sees each point's eroded geometry (A_t, V, L*, bore, A_e) instead of the
    design point's, exactly what ``TimeVaryingCoupledSolver(chug_eroded_geometry=True)`` does.
``start_window`` (D7 E)
    The margin is *graded* from the first fully-open step: the main valves' travel (the drawing's
    ``travel_time``, else the twin's ``Setup.valve_travel_s``) plus ``settle_tau`` line time
    constants. Steps inside that window are evaluated and reported (``worst``) but not graded
    (``settled_min``): every one of them is a quasi-steady part-open state of an algebraic network
    whose number is set by ``dt`` (audit 5.1: 1.367 / 1.308 / 1.161 / 0.797 at 50 / 10 / 5 / 2 ms).

The config basis at the replay points reproduces the replay's ``chug_margin`` exactly (the chamber
is re-solved on the replay's own geometry at the replay's own line-exit pressures, and the gate is
EngineDesign's own ``_chug_fast`` + ``chug_band``); ``check`` in the output says by how much.

Public functions
----------------
``stability_block(prep, result, config=None, basis="config", eroded=False, start_window="auto")``
    -> the ``diagnostics.stability`` dict. Never raises: ``{"available": False, "error": ...}``.
``drawing_feed(prep)`` -> per side, the drawing's lines on the propellant path and their inertance.

Function Documentation

◆ _block()

Dict[str, Any] engine.layerx.diag.stability._block ( Any prep,
Dict[str, Any] result,
Any config,
str basis,
bool eroded,
Any start_window,
float settle_tau,
float tube_modulus = TUBE_MODULUS_PA )
protected

◆ _check()

Optional[Dict[str, Any]] engine.layerx.diag.stability._check ( List[Dict[str, Any]] rows,
Dict[str, Any] rp,
bool eroded )
protected
The config basis against the replay's own ``chug_margin`` at the replay points: the
re-evaluation is the replay's computation, so this should be zero.

Definition at line 938 of file stability.py.

References max.

Referenced by _block().

◆ _coolprop_liquid()

Tuple[float, float, str] engine.layerx.diag.stability._coolprop_liquid ( str fluid,
float T,
float p )
protected
(rho [kg/m3], a [m/s], CoolProp name) of the propellant at (T, p). CoolProp (Bell et al.
2014, Ind. Eng. Chem. Res. 53(6) 2498-2508): the speed of sound of the reference equation of
state at that state, not a handbook constant.

Definition at line 420 of file stability.py.

Referenced by acoustics().

◆ _drawing_feed_at()

Tuple[Dict[str, Dict[str, float]], List[str]] engine.layerx.diag.stability._drawing_feed_at ( Dict[str, Dict[str, Any]] feed_path,
Dict[str, Any] series,
Optional[int] i,
Dict[str, Any] diag )
protected
The drawing basis's ``feed`` override at series index ``i``: per side, the drawing's
inertance and dP = (tank outlet - line exit) + EngineDesign's exit dump. A side with nothing
to give keeps the config's value (the key is left out).

Definition at line 661 of file stability.py.

References _num(), and max.

Referenced by _block().

◆ _feed_summary()

Dict[str, Any] engine.layerx.diag.stability._feed_summary ( Dict[str, Dict[str, Any]] feed_path,
Dict[str, Any] r0 )
protected
Per side, the two bases' feed impedance at point ``r0`` (the graded worst).

Definition at line 958 of file stability.py.

Referenced by _block().

◆ _gate()

Dict[str, Any] engine.layerx.diag.stability._gate ( Dict[str, Any] inp)
protected
EngineDesign's chug gate for one set of stability inputs, with the frequency *at the gate*.

``gate`` is exactly what ``compute_physical_stability`` reports as ``chug_gate_margin`` (the
same ``_chug_fast`` and ``chug_band``). ``f_gate_hz`` is the chug frequency of the loop at the
band point that sets the gate (the worst negative-real-axis crossing of L(iw) there), which is
the frequency the engine would ring at if it chugged; ``f_nominal_hz`` is the one at the
nominal lag, the only one the replay reported (audit 9.4 section 4: 34.6 vs ~22 Hz).

Definition at line 318 of file stability.py.

References _num(), _shift(), and min.

Referenced by _block().

◆ _geometry_at()

Optional[Dict[str, float]] engine.layerx.diag.stability._geometry_at ( Optional[Dict[str, np.ndarray]] geo,
float t,
Optional[int] k )
protected
Geometry at replay point ``k`` (exact) or at time ``t`` (linear between replay points).

Definition at line 281 of file stability.py.

Referenced by _block().

◆ _inputs()

Dict[str, Any] engine.layerx.diag.stability._inputs ( Any stab_config,
float Pc,
Dict[str, Any] diag,
Optional[Dict[str, Any]] feed = None )
protected

Definition at line 568 of file stability.py.

Referenced by _block().

◆ _line_record()

Dict[str, Any] engine.layerx.diag.stability._line_record ( str rid,
str did,
Optional[float] L,
Optional[float] d,
Any edge,
Any length_param,
Any bore_param,
Any elevation = None )
protected

Definition at line 214 of file stability.py.

References _num(), and _param_record().

Referenced by drawing_feed().

◆ _model()

Dict[str, Any] engine.layerx.diag.stability._model ( str basis,
bool eroded,
Dict[str, Any] win,
Dict[str, Any] pick,
Dict[str, Dict[str, Any]] feed_path,
Dict[str, Any] ac,
float E )
protected
The ``model`` block: what produced the margin, and every input with where it came from.

Definition at line 840 of file stability.py.

Referenced by _block().

◆ _num()

Optional[float] engine.layerx.diag.stability._num ( Any v)
protected

◆ _nyquist()

Dict[str, Any] engine.layerx.diag.stability._nyquist ( Dict[str, Any] inp,
Dict[str, Any] gate,
float t )
protected
The open loop L(iw) of the chug model at one point, on a log frequency grid: at the lag
that sets the gate (``re``/``im``) and at the nominal lag (``re_nominal``/``im_nominal``).

The same transfer functions the gate is computed from (``chug._open_loop_grid``):
L(s) = K_c/(theta_c s + 1) * sum_k exp(-s tau_k) / (Z_reg + I_k s + R_k + 1/G_k). The loop is
open-loop stable, so the closed loop is stable when L does not encircle -1 (Nyquist); the gain
margin is 1/|L| where L crosses the negative real axis.

Definition at line 351 of file stability.py.

References _shift().

Referenced by _block().

◆ _param_record()

Dict[str, Any] engine.layerx.diag.stability._param_record ( Any param,
Optional[float] si,
str unit,
str fallback )
protected
``{value, unit, provenance}`` for one drawn number (a feedtwin ``Param``), in SI.

Definition at line 99 of file stability.py.

Referenced by _line_record(), and drawing_feed().

◆ _replay_geometry()

Optional[Dict[str, np.ndarray]] engine.layerx.diag.stability._replay_geometry ( Dict[str, Any] rp,
Any design )
protected
The replay's geometry at its points, with the as-built geometry prepended at Fire (t = 0).

Newer replays carry V, A_e and the bore; an older one has A_t, L*, eps and the barrel
recession, from which the same numbers follow.

Definition at line 240 of file stability.py.

Referenced by _block().

◆ _runner()

Any engine.layerx.diag.stability._runner ( Any prep,
Any config )
protected

Definition at line 109 of file stability.py.

Referenced by _block().

◆ _shift()

List[Any] engine.layerx.diag.stability._shift ( Sequence[Any] streams,
float dtau )
protected
Every stream's lag moved by ``dtau`` [s], floored at 0: chug_band's rule exactly.

Definition at line 313 of file stability.py.

References max.

Referenced by _gate(), _nyquist(), and _tau_sweep().

◆ _solve_point()

Tuple[float, Dict[str, Any]] engine.layerx.diag.stability._solve_point ( Any runner,
Any cfg_now,
float p_o,
float p_f )
protected
EngineDesign's chamber at the line-exit pressures, on ``cfg_now``'s geometry, with the
diagnostics the stability call reads (as ``TimeVaryingCoupledSolver.solve_time_step``).

Definition at line 557 of file stability.py.

Referenced by _block().

◆ _step_point()

Dict[str, Any] engine.layerx.diag.stability._step_point ( Dict[str, Any] series,
int i )
protected
An evaluation point at the twin's own step ``i`` (not a replay point).

Definition at line 577 of file stability.py.

Referenced by _block().

◆ _tau_sweep()

Dict[str, Any] engine.layerx.diag.stability._tau_sweep ( Dict[str, Any] inp,
int n = TAU_SWEEP_POINTS )
protected
Gate margin against the combustion time lag across the model's own band.

The double-time-lag model's unmeasured input is the mixing-lag fraction f in [0, 1]: each
stream's lag is tau_k(f) = tau_k(f0) + (f - f0) tau_mix_basis (``chug_band``). The axis is the
total lag of the rate-limiting stream. A lag model with no band (the d^2-law) is swept over
0.5-1.5 x its own lags instead, and says so.

Definition at line 379 of file stability.py.

References _shift(), max, and min.

Referenced by _block().

◆ _unmeasured()

List[Dict[str, Any]] engine.layerx.diag.stability._unmeasured ( Dict[str, Any] pick,
Dict[str, Dict[str, Any]] feed_path,
Dict[str, Any] win,
float E )
protected
The inputs nobody has measured that move this margin: for the uncertainty sweep.

Definition at line 903 of file stability.py.

Referenced by _block().

◆ _wall_copied()

Optional[str] engine.layerx.diag.stability._wall_copied ( Any prep)
protected
A flag when every line on the drawing carries the same wall thickness with the same
reference across different bores: a value copied from line to line, not measured.

Definition at line 447 of file stability.py.

References max.

Referenced by acoustics().

◆ _with_geometry()

Any engine.layerx.diag.stability._with_geometry ( Any config,
Optional[Dict[str, float]] g )
protected
A copy of ``config`` on geometry ``g``, set exactly as TimeVaryingCoupledSolver sets it.

Definition at line 290 of file stability.py.

Referenced by _block().

◆ acoustics()

Dict[str, Any] engine.layerx.diag.stability.acoustics ( Any prep,
Dict[str, Any] series,
Dict[str, Dict[str, Any]] feed_path,
int i,
Sequence[float] f_chug,
float E = TUBE_MODULUS_PA )
Quarter- and half-wave frequencies of every liquid line on each propellant path, and of the
whole path, at series step ``i``; a mode within ``NEAR_CHUG`` of the chug band is flagged.

Each line: CoolProp's speed of sound at the tank's liquid temperature and the line's mean
pressure (tank outlet and line exit at that step), Korteweg-corrected for the drawing's bore
and wall. f_1/4 = a/(4L) (open at the tank, closed at the injector), f_1/2 = a/(2L). Which end
condition holds is set by the injector's impedance 2 dP_inj/mdot against the line's a/A: on LE4
that ratio is ~0.13 (1.5e6 vs 1.2e7 Pa s/kg on the fuel side), nearer an open end, so the first
mode lies between the two and the quarter-wave is the lower bound -- the side the near-chug
flag should err on. The path
uses its travel time sum(L_i/a_i). ``lumped_error`` is tan(kL)/kL - 1 at the top of the chug
band: how far the lumped inertance L/A the chug model uses is from the line's distributed
impedance there.

Definition at line 475 of file stability.py.

References _coolprop_liquid(), _num(), _wall_copied(), korteweg(), max, min, and near().

Referenced by _block().

◆ drawing_feed()

Dict[str, Dict[str, Any]] engine.layerx.diag.stability.drawing_feed ( Any prep)
Per side (``oxidiser``/``fuel``), the drawing's path from the tank outlet to the injector
inlet as the twin assembled it.

Returns ``{side: {"lines": [...], "others": [...], "inertance": I [1/m] or None,
"flags": [str]}}``. Each line: ``id, label, length_m, bore_m, area_m2, wall_m, inertance``
and the provenance of each number. ``others`` are the inline components on the path (valves,
fittings) with their ``travel_s`` where they are actuated. Read only: the drawing is the feed
system. A line the drawing gives no length or bore keeps the number the twin burned with
(feed-twin's fallback) and is flagged.

Definition at line 127 of file stability.py.

References _line_record(), _num(), and _param_record().

Referenced by _block().

◆ korteweg()

float engine.layerx.diag.stability.korteweg ( float a0,
float rho,
float bore,
float wall,
float E )
Pressure-wave speed in a liquid-filled elastic tube [m/s].

a = a0 / sqrt(1 + K D / (E e)), K = rho a0^2 the liquid's bulk modulus, D the bore, e the wall,
E the tube's Young's modulus: Korteweg, D. J., "Ueber die Fortpflanzungsgeschwindigkeit des
Schalles in elastischen Roehren", Annalen der Physik und Chemie 241(12), 525-542 (1878); the
thin-walled wavespeed of Wylie, Streeter & Suo, Fluid Transients in Systems (Prentice Hall,
1993), with its pipe-support factor c1 = 1 (expansion joints throughout). A tube anchored
against axial movement has c1 = 1 - nu^2 (0.91 for steel), a ~0.3 % faster wave in LE4's
1/2 x 0.035 in. lines: immaterial here, and the slower c1 = 1 is the conservative side for
the near-chug flag. A wall of 0 or less, or no E, is a rigid tube (a = a0).

Definition at line 430 of file stability.py.

Referenced by acoustics().

◆ stability_block()

Dict[str, Any] engine.layerx.diag.stability.stability_block ( Any prep,
Dict[str, Any] result,
Any config = None,
str basis = "config",
bool eroded = False,
Any start_window = "auto",
* ,
float settle_tau = SETTLE_TAU,
float tube_modulus = TUBE_MODULUS_PA )
``diagnostics.stability`` (DATA-CONTRACT section 3) for one Layer X result.

``basis``: ``"config"`` (today's replay numbers, exactly) or ``"drawing"`` (the drawing's
inertance and the twin's line drop as resistance). The other basis is always computed too and
reported under ``other_basis``. ``eroded``: the stability call on each point's eroded geometry.
``start_window``: ``"auto"`` (valve travel + ``settle_tau`` line time constants) or a time
after Fire [s]. Never raises; a failure is ``{"available": False, "error": ...}``.

Definition at line 691 of file stability.py.

References _block().

◆ start_window_of()

Dict[str, Any] engine.layerx.diag.stability.start_window_of ( Any prep,
Dict[str, Any] result,
Dict[str, Dict[str, Any]] feed_path,
Any start_window = "auto",
float settle_tau = SETTLE_TAU )
When the chug margin starts to be graded [s after Fire] (audit D7-E).

``t_open``: the main valves on the propellant paths are fully open. From the recorded valve
state when the run carries one (``result["network"]``), else Fire + the slowest main's travel
(the drawing's ``travel_time``; the twin's ``Setup.valve_travel_s`` where the drawing has none).

``tau_line``: each side's line as an R-L element, tau = I mdot / (2 dP_leg), with I the
drawing's sum of L/A and dP_leg the twin's tank-outlet -> chamber drop at the first fully-open
step (audit 9.5: LOX 1.19 ms, fuel 4.94 ms on the helium drawing at t = 1.0 s). The injector
passages' own inertance is not included (it adds ~10 % LOX, ~2 % fuel there).

The window ends ``settle_tau`` line constants after ``t_open``. ``start_window`` given as a
number overrides it (seconds after Fire).

Definition at line 584 of file stability.py.

References _num(), and max.

Referenced by _block().

Variable Documentation

◆ NEAR_CHUG

float engine.layerx.diag.stability.NEAR_CHUG = 0.20

Definition at line 68 of file stability.py.

◆ NYQUIST_HZ

tuple engine.layerx.diag.stability.NYQUIST_HZ = (2.0, 2000.0, 400)

Definition at line 66 of file stability.py.

◆ PSI

float engine.layerx.diag.stability.PSI = 6894.757293168361

Definition at line 55 of file stability.py.

◆ SETTLE_TAU

float engine.layerx.diag.stability.SETTLE_TAU = 3.0

Definition at line 60 of file stability.py.

◆ SIDES

tuple engine.layerx.diag.stability.SIDES = (("oxidiser", "oxidizer", "O", "ox"), ("fuel", "fuel", "F", "fuel"))

Definition at line 70 of file stability.py.

◆ SOURCE

tuple engine.layerx.diag.stability.SOURCE
Initial value:
1= ("EngineDesign's chug loop (engine/pipeline/stability/chug.py): F(s) = 1 + K_c/(theta_c s + 1) "
2 "sum_k exp(-s tau_k)/(I_k s + R_k + 1/G_k), Nyquist gain margin over the mixing-lag band; double "
3 "time lag after Leonardi, Nasuti, Di Matteo & Steelant, Acta Astronautica 139 (2017) 344-356; feed "
4 "line inertia in the constant-lag chug loop after Summerfield, J. American Rocket Society 21(5) "
5 "(1951) 108-114. Line waves: Korteweg, Annalen der Physik 241(12) (1878) 525-542, with CoolProp "
6 "sound speeds (Bell et al., Ind. Eng. Chem. Res. 53(6) (2014) 2498-2508).")

Definition at line 832 of file stability.py.

◆ START_POINTS_MAX

int engine.layerx.diag.stability.START_POINTS_MAX = 24

Definition at line 62 of file stability.py.

◆ TAU_SWEEP_POINTS

int engine.layerx.diag.stability.TAU_SWEEP_POINTS = 41

Definition at line 64 of file stability.py.

◆ TUBE_MODULUS_PA

float engine.layerx.diag.stability.TUBE_MODULUS_PA = 193.0e9

Definition at line 80 of file stability.py.

◆ TUBE_MODULUS_SOURCE

tuple engine.layerx.diag.stability.TUBE_MODULUS_SOURCE
Initial value:
1= ("assumed: type 316 stainless, 28.0e6 psi (193 GPa) room temperature (producers' data; "
2 "ASME BPVC II-D Table TM-1: 28.3e6 psi at 70 F); the drawing names no material, "
3 "only '316' in its wall reference text")

Definition at line 81 of file stability.py.