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

Functions

Optional[float] _num (Any v, float scale=1.0)
List[Optional[float]] _col (Dict[str, Any] rp, str key)
Optional[float] _r (Optional[float] v, int digits=6)
Any _config_of (Any prep_or_config)
Any _cea_of (Any prep_or_config, Any config, Any cea_cache)
str _provenance (Any obj, str field, str path)
Dict[str, Any] _inp (Any value, str unit, str provenance)
np.ndarray eroded_radius (np.ndarray x, np.ndarray r0, Dict[str, Dict[str, Any]] stations, int k, float x_liner_end, float x_insert_end=0.0)
Dict[str, Any] separation (Sequence[float] t, Sequence[Optional[float]] p_exit_pa, Sequence[Optional[float]] ambient_pa, Sequence[Optional[float]] M_exit, float threshold=SUMMERFIELD_PE_PA)
Dict[str, Any] isp_breakdown (Sequence[float] t, Dict[str, Any] rp, Any cea_cache, float ambient_pa, float zeta_n, str zeta_provenance)
tuple _zeta (Any config)
List[Optional[float]] _interp_onto (Sequence[float] t, Sequence[float] ts, Sequence[Any] ys)
Dict[str, Any] hardware_block (Any prep_or_config, Optional[Dict[str, Any]] replay_result, Optional[Dict[str, Any]] delivered=None, Optional[Dict[str, Any]] series=None, *, Optional[Dict[str, Any]] soak=None, Any cea_cache=None, Optional[float] ambient_pa=None)
Dict[str, Any] _hardware_block (Any prep_or_config, Optional[Dict[str, Any]] rp, Optional[Dict[str, Any]] delivered, Optional[Dict[str, Any]] series, Optional[Dict[str, Any]] soak, Any cea_cache, Optional[float] ambient_pa)
Dict[str, Any] _model (Any config, Dict[str, Any] rp, bool graphite, bool lined, bool case_declared, float half, str back_basis)

Variables

float PSI = 6894.757293168361
float G0 = 9.80665
float SUMMERFIELD_PE_PA = 0.4
float SCHMUCKER_A = 1.88
float SCHMUCKER_N = -0.64

Detailed Description

The chamber and nozzle hardware along a Layer X burn (DATA-CONTRACT ``diagnostics.hardware``).

Everything here is read off EngineDesign's erosion replay (:mod:`engine.layerx.replay`): the coupled
time-varying solver's wall stations, the geometry it rebuilt from them at each replay point, and its
nozzle state. Nothing is solved again except two table look-ups: the ideal vacuum thrust coefficient
from the CEA cache for the Isp breakdown, and the as-built contour from the thermal geometry module.

The block follows the replay's points, not the twin's steps (``t`` and ``index``, the series index
of each point): the replay solves the engine at those points only, and everything between them is an
interpolation (audit 5.3, "never imply 50 ms resolution").

What it reports, per replay point:

* the throat: diameter, area ratio to as built, ``eps = A_e / A_t(t)`` (A_e is fixed: LE4's nozzle
  does not ablate), ``L* = V(t) / A_t(t)`` with V including the liner's recession, and the
  contraction ratio ``A_c / A_t`` at the eroded barrel and throat;
* the wall: the thinnest liner left over the liner stations, and the graphite insert's back-face
  temperature, labelled an *adiabatic upper bound* when no case is declared (D17);
* the contour as built, and the wall at each replay point: the as-built radius plus each station's
  recession, interpolated between stations the way the solver integrates the volume;
* nozzle separation against the ambient the nozzle actually exhausts into (Summerfield; Schmucker);
* the delivered Isp as a waterfall: ideal, less the c* loss, less the nozzle loss;
* the soak-back after shutdown, when :func:`engine.layerx.replay.soak_back` ran.

``hardware_block`` never raises: a block it cannot build is ``{available: False, error}``.

Function Documentation

◆ _cea_of()

Any engine.layerx.diag.hardware._cea_of ( Any prep_or_config,
Any config,
Any cea_cache )
protected

Definition at line 80 of file hardware.py.

Referenced by _hardware_block().

◆ _col()

List[Optional[float]] engine.layerx.diag.hardware._col ( Dict[str, Any] rp,
str key )
protected

Definition at line 60 of file hardware.py.

References _num().

Referenced by _hardware_block(), and isp_breakdown().

◆ _config_of()

Any engine.layerx.diag.hardware._config_of ( Any prep_or_config)
protected
The engine the replay ran: the line-exit runner's config for a ``Prepared`` (its geometry is
the design's), the object itself otherwise.

Definition at line 68 of file hardware.py.

Referenced by _hardware_block().

◆ _hardware_block()

Dict[str, Any] engine.layerx.diag.hardware._hardware_block ( Any prep_or_config,
Optional[Dict[str, Any]] rp,
Optional[Dict[str, Any]] delivered,
Optional[Dict[str, Any]] series,
Optional[Dict[str, Any]] soak,
Any cea_cache,
Optional[float] ambient_pa )
protected

◆ _inp()

Dict[str, Any] engine.layerx.diag.hardware._inp ( Any value,
str unit,
str provenance )
protected

Definition at line 113 of file hardware.py.

Referenced by _model(), isp_breakdown(), and separation().

◆ _interp_onto()

List[Optional[float]] engine.layerx.diag.hardware._interp_onto ( Sequence[float] t,
Sequence[float] ts,
Sequence[Any] ys )
protected

Definition at line 306 of file hardware.py.

References _num().

Referenced by _hardware_block().

◆ _model()

Dict[str, Any] engine.layerx.diag.hardware._model ( Any config,
Dict[str, Any] rp,
bool graphite,
bool lined,
bool case_declared,
float half,
str back_basis )
protected

Definition at line 477 of file hardware.py.

References _inp(), and _provenance().

Referenced by _hardware_block().

◆ _num()

Optional[float] engine.layerx.diag.hardware._num ( Any v,
float scale = 1.0 )
protected

Definition at line 52 of file hardware.py.

Referenced by _col(), _hardware_block(), _interp_onto(), and isp_breakdown().

◆ _provenance()

str engine.layerx.diag.hardware._provenance ( Any obj,
str field,
str path )
protected
Where a config number came from: the schema's default (left unset, or written out equal to
it), or a value the config sets. The config carries no source for either.

Definition at line 93 of file hardware.py.

Referenced by _model().

◆ _r()

Optional[float] engine.layerx.diag.hardware._r ( Optional[float] v,
int digits = 6 )
protected

Definition at line 64 of file hardware.py.

Referenced by _hardware_block(), isp_breakdown(), and separation().

◆ _zeta()

tuple engine.layerx.diag.hardware._zeta ( Any config)
protected

Definition at line 292 of file hardware.py.

Referenced by _hardware_block().

◆ eroded_radius()

np.ndarray engine.layerx.diag.hardware.eroded_radius ( np.ndarray x,
np.ndarray r0,
Dict[str, Dict[str, Any]] stations,
int k,
float x_liner_end,
float x_insert_end = 0.0 )
The wall at replay point ``k``: ``r0(x) + s(x)``, with ``s`` the stations' recession: along the
liner (``x <= x_liner_end``) linear between liner stations and held flat beyond the first and
last; over the whole graphite insert (``x_liner_end < x <= x_insert_end``) the throat station's.

The insert's downstream half recedes too, though ``TimeVaryingCoupledSolver._geometry`` counts
only the upstream half in the chamber volume: the solver's throat is ``D_t0 + 2 s_throat``, so
the drawn wall's narrowest point must be that diameter. Left at the as-built radius, the
downstream half kept the drawn throat at its as-built size while the run reported the throat
area growing 5.7 % (2026-10-03). Downstream of the insert nothing recedes (the solver moves
only the exit area, and only when the nozzle ablates). Lengths in the units of ``x``, ``r0``.

Definition at line 120 of file hardware.py.

References max.

Referenced by _hardware_block().

◆ hardware_block()

Dict[str, Any] engine.layerx.diag.hardware.hardware_block ( Any prep_or_config,
Optional[Dict[str, Any]] replay_result,
Optional[Dict[str, Any]] delivered = None,
Optional[Dict[str, Any]] series = None,
* ,
Optional[Dict[str, Any]] soak = None,
Any cea_cache = None,
Optional[float] ambient_pa = None )
``diagnostics.hardware`` for one burn (DATA-CONTRACT section 3).

``prep_or_config``: the run's ``Prepared`` (preferred: its runner's config and CEA cache are the
replay's own) or the engine config. ``replay_result``: :func:`engine.layerx.replay.replay` of the
final pass. ``delivered``: :func:`engine.layerx.replay.delivered` with ``ambient_psia`` set (the
trajectory's air in flight); separation falls back to the replay's ambient without it.
``series``: the twin's series (only its ``t`` is read, to bound the block). ``soak``: the
:func:`engine.layerx.replay.soak_back` result, else ``replay_result["soak"]``. ``cea_cache``
overrides the CEA table (built from the config when neither it nor a runner is at hand).
``ambient_pa`` is a fallback for a replay that does not carry its own ``ambient_pa``: the Isp
breakdown must use the ambient the replay's thrust was computed at, so the replay's wins.

Never raises: ``{available: False, error}`` on failure.

Definition at line 317 of file hardware.py.

References _hardware_block().

◆ isp_breakdown()

Dict[str, Any] engine.layerx.diag.hardware.isp_breakdown ( Sequence[float] t,
Dict[str, Any] rp,
Any cea_cache,
float ambient_pa,
float zeta_n,
str zeta_provenance )
Delivered Isp as ideal less two losses, at each replay point, closing exactly.

EngineDesign's thrust (engine/core/nozzle.py ``calculate_thrust``) is
``F = zeta_n Cf_vac(P0, eps) P0 A_t - p_a A_e`` with ``P0 = Pc/kappa`` (the Rayleigh loss of a
finite-area chamber), and its flow is ``mdot = P0 A_t / c*`` with ``c* = eta_c* c*_ideal(Pc)``
(chamber_solver.py: c* is referenced to the nozzle's stagnation pressure). So, with
``Isp g0 = F/mdot = eta_c* c*_ideal [zeta_n Cf_vac(P0) - kappa p_a eps / Pc]``:

* ``ideal_s``: the CEA shifting-equilibrium Isp at this point's Pc, O/F and eps(t), at the
  replay's ambient: ``c*_ideal (Cf_vac(Pc, eps) - p_a eps / Pc) / g0``;
* ``cstar_loss_s = (1 - eta_c*) ideal_s``: at a fixed chamber pressure and throat the thrust is
  unchanged and the flow rises by 1/eta_c*, so the whole ideal Isp scales by eta_c*, the
  ambient term included;
* ``nozzle_loss_s``: what remains, ``eta_c* ideal_s - delivered_s``, which is exactly
  ``zeta_n_loss_s = eta_c* c*_ideal (1 - zeta_n) Cf_vac(P0) / g0
  = (1 - zeta_n)/zeta_n (Isp + p_a A_e/(mdot g0))`` plus
  ``stagnation_loss_s = eta_c* c*_ideal [Cf_vac(Pc) - Cf_vac(P0) + (kappa - 1) p_a eps/Pc] / g0``.
  Because c* is referenced to P0, the stagnation loss reaches Isp only through the ambient
  term and the small shift of Cf_vac with pressure (~0.1 s on LE4); in vacuum it vanishes.

Definition at line 209 of file hardware.py.

References _col(), _inp(), _num(), and _r().

Referenced by _hardware_block().

◆ separation()

Dict[str, Any] engine.layerx.diag.hardware.separation ( Sequence[float] t,
Sequence[Optional[float]] p_exit_pa,
Sequence[Optional[float]] ambient_pa,
Sequence[Optional[float]] M_exit,
float threshold = SUMMERFIELD_PE_PA )
Nozzle separation at each point, from the exit pressure, the ambient and the exit Mach number.

* Summerfield: separated when ``p_e/p_a < threshold`` (~0.4).
* Schmucker: separated when ``p_e/p_a < (1.88 M_e - 1)^-0.64``. ``schmucker_pa_crit_psia`` is the
  ambient above which Schmucker predicts separation at this ``p_e``, ``M_e``:
  ``p_e / (1.88 M_e - 1)^-0.64``; ``schmucker_pe_sep_psia`` the exit pressure below which it does
  at this ambient: ``p_a (1.88 M_e - 1)^-0.64``.

Definition at line 148 of file hardware.py.

References _inp(), _r(), and min.

Referenced by _hardware_block().

Variable Documentation

◆ G0

float engine.layerx.diag.hardware.G0 = 9.80665

Definition at line 36 of file hardware.py.

◆ PSI

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

Definition at line 35 of file hardware.py.

◆ SCHMUCKER_A

float engine.layerx.diag.hardware.SCHMUCKER_A = 1.88

Definition at line 48 of file hardware.py.

◆ SCHMUCKER_N

float engine.layerx.diag.hardware.SCHMUCKER_N = -0.64

Definition at line 49 of file hardware.py.

◆ SUMMERFIELD_PE_PA

float engine.layerx.diag.hardware.SUMMERFIELD_PE_PA = 0.4

Definition at line 42 of file hardware.py.