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

Functions

List[int] replay_indices (Sequence[bool] firing, int n=REPLAY_POINTS)
bool erodes (Any config)
Optional[float] _number (Any v, float scale=1.0)
Any _dig (Any d, str path)
Dict[str, Dict[str, Any]] _stations (Sequence[Optional[Dict[str, Dict[str, Any]]]] steps)
Dict[str, Any] _axial (Sequence[float] t, Dict[str, Dict[str, Any]] stations, Sequence[Any] diags)
Dict[str, Any] replay (Prepared prep, Dict[str, Any] series, int n=REPLAY_POINTS, *, Optional[Dict[str, Any]] sidecars=None, bool soak=False, bool chug_eroded_geometry=False)
Dict[str, Any] soak_back (Prepared prep, Dict[str, Any] rp, float factor=SOAK_FACTOR)
Optional[tuple] throat_schedule (Dict[str, Any] rp)
float schedule_change (Optional[tuple] old, Optional[tuple] new)
Dict[str, Any] agreement (Dict[str, Any] rp, Dict[str, Any] series)
List[float] _interp (Sequence[float] t, Sequence[float] xs, Sequence[Optional[float]] ys)
Optional[Dict[str, Any]] delivered (Dict[str, Any] rp, Dict[str, Any] series, float dt)
Dict[str, Any] timeseries_payload (Dict[str, Any] result)

Variables

int REPLAY_POINTS = 28
float THROAT_TOLERANCE = 2.0e-4
int MAX_PASSES = 4
dict DIAGNOSTIC_COLUMNS
dict RESULT_COLUMNS
dict STATION_FIELDS
float SOAK_FACTOR = 3.0

Detailed Description

Phase 3: EngineDesign replays the twin's burn, with the chamber eroding as it goes.

The engine card (phase 2) is EngineDesign's injector and chamber at the geometry they were
built with. A real burn does not keep that geometry. The graphite throat and the ablative liner
recede, and on the 6.8 kN engine EngineDesign's coupled solver puts the throat ~5-6 % larger in
area by burnout. At the same line pressures that is ~3 % more flow and ~2.5 % less chamber
pressure late in the burn: the card alone cannot see it, and the feed system feels it, because
more flow drains the tanks faster and droops the regulator harder.

So the burn is closed in two passes that are iterated to agreement:

pass 1, the twin
    The feed system burns against the card. The card's chamber divides by the throat area,
    so the throat history from the previous replay is applied step by step (the first pass
    uses the as-built throat).
pass 2, EngineDesign
    The coupled time-varying solver (``TimeVaryingCoupledSolver``) runs at the line-exit
    pressures the twin delivered, with ablative and graphite recession integrated through
    the burn. The config is the line-exit copy (``engine/layerx/card.py``), so its "tank"
    pressures are exactly the twin's injector-face pressures.

Iterate until the throat history stops moving, which is usually two passes. The feed-system
answers (tank pressures, depletion time) are the twin's last pass. The engine answers (chamber
pressure, flow, thrust, Isp, recession) are EngineDesign's replay of that pass. Where the two
overlap, flow at the same inlet pressures, the disagreement is reported as the agreement, so
the hand-off between them is checked rather than assumed.

Function Documentation

◆ _axial()

Dict[str, Any] engine.layerx.replay._axial ( Sequence[float] t,
Dict[str, Dict[str, Any]] stations,
Sequence[Any] diags )
protected
The axial profiles over the burn, for the ``axial`` sidecar (DATA-CONTRACT §4).

Two bases, kept apart because they are not the same physics:

* the top-level arrays are the transient wall stations (x along the wall, one column per
  station, one row per replay point): the gas-side load at each station's own surface
  temperature, that temperature, and the recession. These are what the erosion integrates.
* ``profile`` is the chamber solve's whole-contour Bartz + radiation flux (278 points face to
  exit) at the quasi-steady liner surface temperature (``ablative_cooling.liner_response``,
  ``with_profile``): a display of where the gas loads the wall, evaluated at one wall
  temperature everywhere, not the transient wall. Each step's profile is drawn on its own
  redrawn contour; it is interpolated here onto the first step's x so the rows line up.

Definition at line 161 of file replay.py.

References _dig(), and _number().

Referenced by replay().

◆ _dig()

Any engine.layerx.replay._dig ( Any d,
str path )
protected

Definition at line 72 of file replay.py.

Referenced by _axial(), and replay().

◆ _interp()

List[float] engine.layerx.replay._interp ( Sequence[float] t,
Sequence[float] xs,
Sequence[Optional[float]] ys )
protected

Definition at line 468 of file replay.py.

Referenced by delivered().

◆ _number()

Optional[float] engine.layerx.replay._number ( Any v,
float scale = 1.0 )
protected

Definition at line 64 of file replay.py.

Referenced by _axial(), _stations(), and replay().

◆ _stations()

Dict[str, Dict[str, Any]] engine.layerx.replay._stations ( Sequence[Optional[Dict[str, Dict[str, Any]]]] steps)
protected
The solver's per-step station read-outs as one record per station, columns over the replay.

Definition at line 144 of file replay.py.

References _number().

Referenced by replay().

◆ agreement()

Dict[str, Any] engine.layerx.replay.agreement ( Dict[str, Any] rp,
Dict[str, Any] series )
The twin's flows and chamber pressure against EngineDesign's replay at the same instants
and inlet pressures: what the hand-off between the two passes leaves open.

Definition at line 454 of file replay.py.

References max.

◆ delivered()

Optional[Dict[str, Any]] engine.layerx.replay.delivered ( Dict[str, Any] rp,
Dict[str, Any] series,
float dt )
The engine's answers over the burn, from the replay, on the twin's firing steps.

Thrust, chamber pressure, flow and Isp are EngineDesign's (interpolated between replay
points; they are smooth). Burn time and the propellant used are the twin's, whose last pass
already ran with the eroding throat.

Definition at line 476 of file replay.py.

References _interp(), max, and min.

◆ erodes()

bool engine.layerx.replay.erodes ( Any config)
True when the engine has a wall that recedes: a graphite throat insert or an ablative liner.
Such an engine is replayed on EngineDesign's coupled time-varying solver, and only on it.

Definition at line 56 of file replay.py.

Referenced by replay().

◆ replay()

Dict[str, Any] engine.layerx.replay.replay ( Prepared prep,
Dict[str, Any] series,
int n = REPLAY_POINTS,
* ,
Optional[Dict[str, Any]] sidecars = None,
bool soak = False,
bool chug_eroded_geometry = False )
EngineDesign's coupled time-varying solve at the twin's line-exit pressures.

An engine with a graphite insert or an ablative liner (:func:`erodes`) is replayed on the
coupled solver only (``track_ablative_geometry=True, strict_erosion=True``). The replay used to
pass ``None``, which tracked geometry only when the liner was enabled *and* tracked: a
graphite-only engine, or one with ``track_geometry_evolution: false``, replayed through the
legacy constant-geometry loop with zero erosion and no warning (audit 5.3). If the coupled
solve fails now, the replay is unavailable and says why.

``sidecars``, when a dict, receives ``sidecars["axial"]`` (:func:`_axial`), too large for the
run record. ``soak`` adds the soak-back after this burn (:func:`soak_back`) as ``["soak"]``;
pass it on the final replay of a run only (or call :func:`soak_back` after it).
``chug_eroded_geometry`` hands the chug analysis each step's eroded geometry (default off,
the previous behaviour; D7-D).

Definition at line 211 of file replay.py.

References _axial(), _dig(), _number(), _stations(), erodes(), replay_indices(), and soak_back().

◆ replay_indices()

List[int] engine.layerx.replay.replay_indices ( Sequence[bool] firing,
int n = REPLAY_POINTS )
Indices of firing steps to replay: evenly spread, first and last always included.

Definition at line 47 of file replay.py.

Referenced by replay().

◆ schedule_change()

float engine.layerx.replay.schedule_change ( Optional[tuple] old,
Optional[tuple] new )
Largest relative change of the throat history between two passes.

Definition at line 443 of file replay.py.

◆ soak_back()

Dict[str, Any] engine.layerx.replay.soak_back ( Prepared prep,
Dict[str, Any] rp,
float factor = SOAK_FACTOR )
The soak-back after the burn ``rp`` replayed (DATA-CONTRACT diagnostics.hardware.soak).

Uses the wall state the coupled solver ended that replay with (the runner keeps its last
solver), continued with the hot face adiabatic for ``factor`` x the slowest layer's L^2/alpha
(:meth:`TimeVaryingCoupledSolver.soak_back_history`). Call it after the final replay of a run:
a later replay replaces the wall state, and that is refused rather than reported.

The back face is adiabatic in the wall model. With no case declared (LE4:
``stainless_steel_case: null``) the insert's back face is therefore an *adiabatic upper bound*:
nothing behind it takes heat (audit D17). With a case declared it is the case's outer face,
still adiabatic to the room.

Definition at line 332 of file replay.py.

References max.

Referenced by replay().

◆ throat_schedule()

Optional[tuple] engine.layerx.replay.throat_schedule ( Dict[str, Any] rp)
``(t, A_throat)`` from a replay, for the next twin pass; ``None`` without one.

Definition at line 428 of file replay.py.

◆ timeseries_payload()

Dict[str, Any] engine.layerx.replay.timeseries_payload ( Dict[str, Any] result)
The burn in the shape the Time-Series tab stores (``api/client.ts TimeSeriesData``), so
Forward mode's burn view and the Flight tab read a Layer X run exactly as they read a
Time-Series run. Engine quantities from the replay when there is one; feed-system
quantities from the twin. Time starts at the Fire command, with a sample there.

Definition at line 529 of file replay.py.

Variable Documentation

◆ DIAGNOSTIC_COLUMNS

dict engine.layerx.replay.DIAGNOSTIC_COLUMNS
Initial value:
1= {
2 "momentum_ratio": ("momentum_ratio_R", 1.0),
3 "rupe_M": ("rupe_M", 1.0),
4 "rupe_Em": ("cstar_efficiency.rupe_Em", 1.0),
5 "eta_vap": ("cstar_efficiency.eta_vaporization", 1.0),
6 "eta_mix": ("cstar_efficiency.eta_mixing", 1.0),
7 "eta_heat_loss": ("cstar_efficiency.eta_heat_loss", 1.0),
8 "kappa": ("stagnation_loss_kappa", 1.0),
9 "Cd_O": ("Cd_O", 1.0),
10 "Cd_F": ("Cd_F", 1.0),
11 "Cd_eff_O": ("Cd_eff_manifold_O", 1.0),
12 "Cd_eff_F": ("Cd_eff_manifold_F", 1.0),
13 "smd_O_um": ("D32_O", 1e6),
14 "smd_F_um": ("D32_F", 1e6),
15 "v_O_m_s": ("u_O", 1.0),
16 "v_F_m_s": ("u_F", 1.0),
17 "dp_injector_O_psi": ("delta_p_injector_O", 1.0 / PSI),
18 "dp_injector_F_psi": ("delta_p_injector_F", 1.0 / PSI),
19}

Definition at line 83 of file replay.py.

◆ MAX_PASSES

int engine.layerx.replay.MAX_PASSES = 4

Definition at line 44 of file replay.py.

◆ REPLAY_POINTS

int engine.layerx.replay.REPLAY_POINTS = 28

Definition at line 40 of file replay.py.

◆ RESULT_COLUMNS

dict engine.layerx.replay.RESULT_COLUMNS
Initial value:
1= {
2 "M_exit": ("M_exit", 1.0),
3 "D_throat_mm": ("D_throat", 1e3),
4 "D_chamber_mm": ("D_chamber", 1e3),
5 "V_chamber_m3": ("V_chamber", 1.0),
6 "A_exit_m2": ("A_exit", 1.0),
7 "contraction_ratio": ("contraction_ratio", 1.0),
8 "cstar_ideal": ("cstar_ideal", 1.0),
9 "chug_frequency_hz": ("chugging_frequency", 1.0),
10 "T_graphite_back_K": ("T_graphite_back", 1.0),
11 "T_bondline_K": ("T_bondline", 1.0),
12 "T_bondline_peak_K": ("T_bondline_peak", 1.0),
13 "char_depth_chamber_mm": ("char_depth_chamber", 1e3),
14 "recession_liner_peak_mm": ("recession_liner_peak", 1e3),
15 "x_liner_peak_mm": ("x_liner_peak", 1e3),
16 "q_conv_throat_MW_m2": ("q_conv_throat", 1e-6),
17 "q_rad_throat_MW_m2": ("q_rad_throat", 1e-6),
18 "q_chem_throat_MW_m2": ("q_chem_throat", 1e-6),
19 "q_conv_chamber_MW_m2": ("q_conv_chamber", 1e-6),
20 "q_rad_chamber_MW_m2": ("q_rad_chamber", 1e-6),
21 "graphite_recession_rate_mm_s": ("graphite_recession_rate", 1e3),
22 "liner_recession_rate_mm_s": ("ablative_recession_rate", 1e3),
23}

Definition at line 106 of file replay.py.

◆ SOAK_FACTOR

float engine.layerx.replay.SOAK_FACTOR = 3.0

Definition at line 329 of file replay.py.

◆ STATION_FIELDS

dict engine.layerx.replay.STATION_FIELDS
Initial value:
1= {
2 "recession_mm": ("receded", 1e3),
3 "remaining_mm": ("remaining", 1e3),
4 "T_surface_K": ("T_surface", 1.0),
5 "T_back_K": ("T_back", 1.0),
6 "T_interface_K": ("T_interface", 1.0),
7 "q_net_MW_m2": ("q_net", 1e-6),
8 "q_conv_MW_m2": ("q_conv", 1e-6),
9 "q_rad_MW_m2": ("q_rad", 1e-6),
10 "q_chem_MW_m2": ("q_chem", 1e-6),
11}

Definition at line 131 of file replay.py.

◆ THROAT_TOLERANCE

float engine.layerx.replay.THROAT_TOLERANCE = 2.0e-4

Definition at line 42 of file replay.py.