|
STAR
Cal STAR — firmware, DAQ server, and engine design
|
Functions | |
| Dict[str, float] | calculate_chugging_frequency (float chamber_volume, float throat_area, float cstar, float gamma, float Pc, Optional[float] R=None, Optional[float] Tc=None) |
| Dict[str, Any] | calculate_acoustic_modes (float chamber_length, float chamber_diameter, float gas_temperature, float gamma, float R) |
| Dict[str, Any] | analyze_feed_system_stability (float feed_line_length, float feed_line_diameter, float propellant_density, float bulk_modulus, float flow_velocity, Optional[float] pressure_drop=None, *, Optional[float] wall_modulus_pa=None, Optional[float] wall_thickness_m=None, Optional[float] valve_closure_time_s=None) |
| float | gain_margin_db (float gain_margin) |
| float | stability_score (float min_margin) |
| bool | stability_state_ok (str state, bool require_stable_state) |
| float | _stability_requirement (config) |
| str | classify_stability (float chug_gm_nominal, float chug_gate, float acoustic_gate, float acoustic_alpha_nominal, bool acoustic_gated, float requirement) |
| _fluid_attr (fluids, key, attr, default) | |
| _feed_attr (config, key, attr, default) | |
| Optional[float] | _coolprop_critical_temperature (str canon) |
| str | _fluid_name (config, str key) |
| float | _fluid_thermo (config, str key, str attr) |
| str | _injection_phase (config, str key) |
| Tuple[float, float] | _feed_geometry (config, str side) |
| Optional[float] | _coolprop_bulk_modulus (str canon, float T, float P) |
| float | _liquid_bulk_modulus (config, str key, float P_line, str record_name) |
| Tuple[Optional[float], Optional[float], str] | _feed_wall (config, str side) |
| Tuple[float, float] | _chamber_dims (config, cg) |
| Tuple[float, float] | _jet_geometry (config, Dict[str, Any] diagnostics, str side) |
| StabilityConfig | _stability_config (config) |
| Dict[str, float] | _feed_override (Optional[Dict[str, Dict[str, float]]] feed, str side) |
| Dict[str, Any] | build_stability_inputs (config, float Pc, float MR, float mdot_total, float cstar, float gamma, float R, float Tc, Dict[str, Any] diagnostics, Any cg, *, Optional[Dict[str, float]] overrides=None, Optional[Dict[str, Dict[str, float]]] feed=None) |
| Dict[str, Any] | _chug_fast (streams, chamber) |
| Optional[Dict[str, Any]] | chug_band (Dict[str, Any] inp, float nominal_gm, int n_pts=5) |
| float | _chug_feed_drop (Any config, str side, float dp_feed, float mdot, float rho) |
| Optional[Dict[str, Any]] | compute_physical_stability (config, float Pc, float MR, float mdot_total, float cstar, float gamma, float R, float Tc, Dict[str, Any] diagnostics, Any cg) |
| Dict[str, Any] | comprehensive_stability_analysis (PintleEngineConfig config, float Pc, float MR, float mdot_total, float cstar, float gamma, float R, float Tc, Dict[str, Any] diagnostics) |
| List[str] | _generate_stability_recommendations (str stability_state, Dict[str, float] chugging, Dict[str, Any] acoustic, Dict[str, float] feed_system, List[Dict[str, Any]] mode_coupling, float Lstar) |
Variables | |
| tuple | ACOUSTIC_GATE_MODES = ("report_only", "nominal_phase", "worst_phase") |
| dict | _FLUID_THERMO_FALLBACKS |
| dict | _THERMO_INDEX |
| dict | _GENERIC_THERMO |
| dict | _COOLPROP_NAMES |
| float | _TUBE_E_STAINLESS = 193.0e9 |
Stability analysis for combustion and feed system dynamics.
1. Combustion stability: chug (feed-coupled, low frequency) and acoustic (chamber modes).
2. Feed-line acoustics and the water-hammer bound, both lines.
3. Overall classification at an operating point.
Every gate-facing margin is a physical ratio that is 1 at neutral stability:
* chug: the Nyquist gain margin of the feed-chamber loop (the factor the loop gain can rise
before a pole crosses into the right half-plane), taken at the low end of the unmeasured
mixing-lag band;
* acoustic: damping/driving for the worst mode (= n_crit/n), gated only when
``stability.acoustic_gate`` asks for it -- by default it is reported, not gated (acoustic.py).
They are compared directly with ``design_requirements.min_stability_margin``. The tanh remaps that
used to sit between the physics and the gate (and saturated at 1.3) are gone.
|
protected |
(L_chamber, D_chamber) [m]. The solved unified geometry first: its ``length`` is the total chamber length and its ``chamber_diameter`` is the cylindrical bore, which is what the transverse acoustic modes live in. Legacy configs fall back to ``chamber.length`` and the volume-mean diameter; anything still missing is a recorded assumption.
Definition at line 529 of file analysis.py.
Referenced by build_stability_inputs(), and comprehensive_stability_analysis().
|
protected |
Fast chug margin through the compiled kernel when the accelerator is on, else Python.
Definition at line 897 of file analysis.py.
Referenced by chug_band(), and compute_physical_stability().
|
protected |
The feed drop the chug loop sees as resistance: the line's, without the supply's share.
Definition at line 950 of file analysis.py.
References max.
Referenced by build_stability_inputs().
|
protected |
Isentropic bulk modulus ``rho a^2`` [Pa] from CoolProp at (T, P), or None. Cached on the rounded state: the value cannot change within a process, and PropsSI per candidate would be a real cost.
Definition at line 462 of file analysis.py.
Referenced by _liquid_bulk_modulus().
|
protected |
Critical temperature [K] from CoolProp for a canonical fluid name, or None. Cached: the fast stability tier runs on every optimizer candidate, and a PropsSI call per candidate would be a real cost for a value that cannot change within a process.
Definition at line 362 of file analysis.py.
Referenced by _fluid_thermo().
|
protected |
Definition at line 322 of file analysis.py.
Referenced by _feed_geometry().
|
protected |
(length [m], flow area [m^2]) of one feed line for the chug inertance L/A. Length comes from ``feed_system.<side>.length`` -- a field that did not exist until now, which is why the model used to carry a hardcoded 0.305 m for every engine. Area is the schema-derived ``A_hydraulic`` (pi d^2/4 unless the user gave a non-circular passage).
Definition at line 438 of file analysis.py.
References _feed_attr().
Referenced by build_stability_inputs(), and comprehensive_stability_analysis().
|
protected |
The caller's feed impedance for one side (``feed[side]`` or ``feed["O"/"F"]``), validated. Only ``inertance`` [1/m] and ``dP_feed`` [Pa] are read. A value that is not a finite, non-negative number is refused rather than clipped: it would otherwise move the chug margin with nothing in the payload saying why.
Definition at line 597 of file analysis.py.
Referenced by build_stability_inputs().
|
protected |
(Young's modulus [Pa], wall [m], note) for the Korteweg wave-speed correction. The wall comes from a ``*_TUBE_035``-style ``line_size`` (0.035 in); a pipe/fitting size or a bare bore carries no wall, and the line is then treated as rigid (an upper bound on a) and said so. The tube material is not in the config, so E is a recorded assumption.
Definition at line 506 of file analysis.py.
Referenced by comprehensive_stability_analysis().
|
protected |
Config-first fluid property lookup. ``default=None`` is allowed and returned as-is when the property is missing — callers use that to route the fallback through the assumptions registry (UNIFICATION P2c) instead of silently substituting.
Definition at line 308 of file analysis.py.
Referenced by _fluid_thermo(), _injection_phase(), _liquid_bulk_modulus(), and build_stability_inputs().
|
protected |
Definition at line 379 of file analysis.py.
Referenced by _fluid_thermo(), _injection_phase(), _liquid_bulk_modulus(), and build_stability_inputs().
|
protected |
``fluids[key].attr`` from the config; else CoolProp for the named fluid; else the handbook table; else a generic value. Every fallback is recorded, and the generic one says outright that the fluid was unrecognised so it reads as "fix the config", not as a property.
Definition at line 387 of file analysis.py.
References _coolprop_critical_temperature(), _fluid_attr(), and _fluid_name().
Referenced by _injection_phase(), build_stability_inputs(), and comprehensive_stability_analysis().
|
protected |
Generate stability improvement recommendations based on analysis.
Definition at line 1225 of file analysis.py.
Referenced by comprehensive_stability_analysis().
|
protected |
``"liquid"`` or ``"gas"`` at the injector face. Explicit config wins. Otherwise: supercritical at the tank temperature is gas-like, and a fluid whose vapour pressure at its own bulk temperature exceeds the chamber pressure arrives as vapour. Both inferences are recorded — getting this wrong changes which time lags exist at all, so it must never be a silent guess.
Definition at line 411 of file analysis.py.
References _fluid_attr(), _fluid_name(), and _fluid_thermo().
Referenced by build_stability_inputs().
|
protected |
(jet/post inner diameter [m], injection velocity [m/s]) for one stream. These are Leonardi eq. 6-7's ``D_l`` and ``u_l``. Both come from whichever injector the config actually names -- the solved closure diagnostics first (every injector model publishes ``u_O``/ ``u_F``), then the injector's own geometry block. Returns NaN rather than a stand-in when the injector type carries no equivalent dimension; the lag model then drops the atomization term and records it, instead of inventing a jet. Impinging -> the jet diameter. Coaxial -> the core port (oxidizer) and the annulus hydraulic diameter (fuel), which is what L17 calls the liquid post. Pintle -> the tip orifice (oxidizer) and the annular gap's hydraulic diameter, 2*h_gap (fuel).
Definition at line 550 of file analysis.py.
Referenced by build_stability_inputs().
|
protected |
``fluids[key].bulk_modulus_pa``; else CoolProp rho*a^2 at the fluid temperature and line pressure; else a recorded generic value. LOX at 90 K / 4 MPa is 0.98 GPa, not the 1.5 GPa order-of-magnitude figure that used to stand in for it.
Definition at line 480 of file analysis.py.
References _coolprop_bulk_modulus(), _fluid_attr(), and _fluid_name().
Referenced by build_stability_inputs(), and comprehensive_stability_analysis().
|
protected |
Definition at line 592 of file analysis.py.
Referenced by build_stability_inputs().
|
protected |
Gate threshold for 'stable': design_requirements.min_stability_margin relaxed by stability_margin_handicap exactly as Layer 1 relaxes it; the schema default when absent.
Definition at line 273 of file analysis.py.
References max.
Referenced by comprehensive_stability_analysis().
| Dict[str, Any] engine.pipeline.stability.analysis.analyze_feed_system_stability | ( | float | feed_line_length, |
| float | feed_line_diameter, | ||
| float | propellant_density, | ||
| float | bulk_modulus, | ||
| float | flow_velocity, | ||
| Optional[float] | pressure_drop = None, | ||
| * | , | ||
| Optional[float] | wall_modulus_pa = None, | ||
| Optional[float] | wall_thickness_m = None, | ||
| Optional[float] | valve_closure_time_s = None ) |
Feed-line acoustics and the water-hammer spike for one propellant line.
Parameters
----------
feed_line_length, feed_line_diameter : float
Line length and bore [m]
propellant_density, bulk_modulus : float
Liquid density [kg/m^3] and isentropic bulk modulus [Pa]
flow_velocity : float
Mean line velocity [m/s]
pressure_drop : float, optional
Unused; kept so old callers still bind.
wall_modulus_pa, wall_thickness_m : float, optional
Tube Young's modulus and wall. With both, the wave speed carries the Korteweg wall
compliance ``a = a_liquid / sqrt(1 + K D / (E e))`` (Wylie & Streeter, Fluid Transients);
without, the rigid-wall ``sqrt(K/rho)`` is an upper bound.
valve_closure_time_s : float, optional
Valve closure time. None = instantaneous: the Joukowsky bound ``rho a v``. For a closure
slower than the round trip ``2L/a`` the spike is ``rho a v (2L/a) / t_c`` (Michaud).
Returns
-------
dict
- pogo_frequency: quarter-wave line mode (tank end open, injector end closed) [Hz]
- surge_frequency: half-wave line mode (closed-closed) [Hz]
- sound_speed: wave speed in the line, wall compliance included when given [m/s]
- sound_speed_liquid: sqrt(K/rho) [m/s]
- korteweg_factor: a_liquid / a [-] (1 = rigid wall)
- water_hammer_pressure: valve-closure spike [Pa]
- water_hammer_basis: which formula produced it
The feed-coupled *stability* margin is the chug gain margin from ``chug.py``; the caller writes
it into this dict as ``stability_margin``. ``water_hammer_margin`` (steady drop over the
instantaneous-closure spike) compared two unrelated pressures and has been removed.
Definition at line 154 of file analysis.py.
References max.
Referenced by comprehensive_stability_analysis().
| Dict[str, Any] engine.pipeline.stability.analysis.build_stability_inputs | ( | config, | |
| float | Pc, | ||
| float | MR, | ||
| float | mdot_total, | ||
| float | cstar, | ||
| float | gamma, | ||
| float | R, | ||
| float | Tc, | ||
| Dict[str, Any] | diagnostics, | ||
| Any | cg, | ||
| * | , | ||
| Optional[Dict[str, float]] | overrides = None, | ||
| Optional[Dict[str, Dict[str, float]]] | feed = None ) |
Extract chug/acoustic model inputs from config + diagnostics. Shared by the fast path
(compute_physical_stability) and the rich report (report.py) so they use IDENTICAL extraction.
[Phys §3.2, §4, §5]
Sources, in order: solved geometry (``cg``), the closure diagnostics of this evaluation, the
config (``fluids`` for the propellants, ``feed_system`` for the plumbing, ``stability`` for the
model calibration), and finally recorded assumptions -- never a silent constant.
``feed`` (opt-in, default None = the config's plumbing, exactly as before): the feed impedance
of each side stated by the caller, ``{"oxidizer"|"O": {"inertance": I [1/m], "dP_feed": dp [Pa]},
"fuel"|"F": {...}}``. ``inertance`` replaces ``feed_system.<side>.length / A_hydraulic`` (the
caller has summed L/A over the lines it knows, e.g. a P&ID drawing's); ``dP_feed`` replaces the
closure's feed drop as the steady drop the linearised resistance ``R = 2 dp / mdot`` is taken
from, *whole*: the ``supply_K`` share is not subtracted from it, because the caller's drop runs
from the tank outlet and the supply is upstream of the tank. Either key may be given alone.
Definition at line 619 of file analysis.py.
References _chamber_dims(), _chug_feed_drop(), _feed_geometry(), _feed_override(), _fluid_attr(), _fluid_name(), _fluid_thermo(), _injection_phase(), _jet_geometry(), _liquid_bulk_modulus(), _stability_config(), max, and min.
Referenced by compute_physical_stability().
| Dict[str, Any] engine.pipeline.stability.analysis.calculate_acoustic_modes | ( | float | chamber_length, |
| float | chamber_diameter, | ||
| float | gas_temperature, | ||
| float | gamma, | ||
| float | R ) |
Calculate acoustic resonance frequencies for longitudinal and transverse modes.
Parameters
----------
chamber_length : float
Chamber length [m]
chamber_diameter : float
Chamber diameter [m]
gas_temperature : float
Gas temperature [K]
gamma : float
Specific heat ratio [-]
R : float
Gas constant [J/(kg K)]
Returns
-------
dict
- longitudinal_modes: list of longitudinal mode frequencies [Hz]
- transverse_modes: list of first few transverse mode frequencies [Hz]
- sound_speed: sound speed [m/s]
Definition at line 94 of file analysis.py.
References max.
Referenced by comprehensive_stability_analysis().
| Dict[str, float] engine.pipeline.stability.analysis.calculate_chugging_frequency | ( | float | chamber_volume, |
| float | throat_area, | ||
| float | cstar, | ||
| float | gamma, | ||
| float | Pc, | ||
| Optional[float] | R = None, | ||
| Optional[float] | Tc = None ) |
Order-of-magnitude chug (bulk-mode) frequency estimates from chamber geometry alone.
Two estimates: the residence-time frequency ``1 / (2 pi tau_res)`` with ``tau_res = L*/c*``, and
a Helmholtz bulk mode using the throat as the neck. These are *placeholders* -- the physical chug
frequency comes from the feed-coupled loop in ``chug.py`` and overwrites ``frequency`` in
``comprehensive_stability_analysis``. The old heuristic "stability_index" / "stability_margin"
that used to ride along here (floored at 0.4 and mapped to a margin so that "reasonable designs
achieve required margins") was not a physical quantity and has been removed; margins come from
the gain-margin model only.
Returns
-------
dict
- frequency: Helmholtz estimate when gas properties are known, else the residence estimate [Hz]
- frequency_residence, frequency_helmholtz: the two estimates [Hz] (nan if unavailable)
- period: 1 / frequency [s]
- tau_residence: L* / c* [s]
- Lstar: characteristic length [m]
Definition at line 31 of file analysis.py.
References max.
Referenced by comprehensive_stability_analysis().
| Optional[Dict[str, Any]] engine.pipeline.stability.analysis.chug_band | ( | Dict[str, Any] | inp, |
| float | nominal_gm, | ||
| int | n_pts = 5 ) |
Chug gain margin over the unmeasured mixing-lag fraction band ``inp["chug_band"]``. tau_mix = f * tau_mix_basis is shared by both streams, so moving f shifts every stream's lag by (f - f_nominal) * basis. GM is not monotone in the lag in general, so the band is sampled rather than read off its ends. None when there is no band (d^2-law, or a fixed override).
Definition at line 911 of file analysis.py.
References _chug_fast(), max, and min.
Referenced by compute_physical_stability().
| str engine.pipeline.stability.analysis.classify_stability | ( | float | chug_gm_nominal, |
| float | chug_gate, | ||
| float | acoustic_gate, | ||
| float | acoustic_alpha_nominal, | ||
| bool | acoustic_gated, | ||
| float | requirement ) |
'unstable' / 'marginal' / 'stable' / 'unknown' from the physical margins.
unstable: the model predicts growth at its nominal inputs (chug GM < 1, or a gated acoustic
mode with alpha > 0 / margin < 1);
stable: every gated margin clears max(1, requirement);
marginal: predicted stable, but some gated margin falls short of the requirement (for chug,
possibly only at the pessimistic end of the mixing-lag band);
unknown: a gated number is missing -- never passes.
Definition at line 285 of file analysis.py.
References max.
Referenced by comprehensive_stability_analysis().
| Dict[str, Any] engine.pipeline.stability.analysis.comprehensive_stability_analysis | ( | PintleEngineConfig | config, |
| float | Pc, | ||
| float | MR, | ||
| float | mdot_total, | ||
| float | cstar, | ||
| float | gamma, | ||
| float | R, | ||
| float | Tc, | ||
| Dict[str, Any] | diagnostics ) |
Comprehensive stability analysis combining combustion, acoustic, and feed system.
Returns
-------
dict with keys
- stability_state: "stable", "marginal", "unstable", or "unknown" (model not evaluable;
never passes a gate)
- stability_score: display map of the limiting gate margin, see ``stability_score``
- is_stable: backward compatibility boolean
- chugging: frequencies, ``stability_margin`` (gate: GM at the low end of the mixing-lag
band), ``chug_gain_margin`` (nominal GM), ``chug_gain_margin_db``, ``chug_gm_band``
- acoustic: mode frequencies, ``stability_margin`` (gate; +inf when report-only),
``gate_status``, nominal and worst-phase margins
- feed_system: oxidizer-line acoustics (legacy top level) and ``feed_lines`` for both
- mode_coupling: list of potentially coupled mode pairs
- issues, recommendations, Lstar
Definition at line 1012 of file analysis.py.
References _chamber_dims(), _feed_geometry(), _feed_wall(), _fluid_thermo(), _generate_stability_recommendations(), _liquid_bulk_modulus(), _stability_requirement(), analyze_feed_system_stability(), calculate_acoustic_modes(), calculate_chugging_frequency(), classify_stability(), compute_physical_stability(), gain_margin_db(), max, min, and stability_score().
| Optional[Dict[str, Any]] engine.pipeline.stability.analysis.compute_physical_stability | ( | config, | |
| float | Pc, | ||
| float | MR, | ||
| float | mdot_total, | ||
| float | cstar, | ||
| float | gamma, | ||
| float | R, | ||
| float | Tc, | ||
| Dict[str, Any] | diagnostics, | ||
| Any | cg ) |
Build inputs and run the FAST tiers (per-eval path). [Phys §3.2 fast, §4.2 fast; plan A4] ``chug_gate_margin`` is the Nyquist GM at the low end of the mixing-lag band (the nominal GM when there is no band); ``acoustic_gate_margin`` is damping/driving per ``stability.acoustic_gate``, +inf when the acoustic model is report-only. Both are 1 at neutral stability.
Definition at line 961 of file analysis.py.
References _chug_fast(), build_stability_inputs(), and chug_band().
Referenced by comprehensive_stability_analysis().
| float engine.pipeline.stability.analysis.gain_margin_db | ( | float | gain_margin | ) |
20 log10(GM) [dB]; NaN for a non-positive or non-finite margin.
Definition at line 249 of file analysis.py.
Referenced by comprehensive_stability_analysis().
| float engine.pipeline.stability.analysis.stability_score | ( | float | min_margin | ) |
Display score in [0, 1] of the limiting gate margin: ``clip((m - 0.85) / 0.45, 0, 1)``. A fixed linear map with no physics of its own: score s <=> margin 0.85 + 0.45 s, so a ``min_stability_score`` of 0.58 is a margin floor of 1.111. Non-finite margin -> 0 (fail closed).
Definition at line 256 of file analysis.py.
Referenced by comprehensive_stability_analysis().
| bool engine.pipeline.stability.analysis.stability_state_ok | ( | str | state, |
| bool | require_stable_state ) |
The state test Layer 1 means by ``require_stable_state``: True -> only 'stable' passes; False -> 'stable' or 'marginal'. 'unstable' and 'unknown' never pass.
Definition at line 267 of file analysis.py.
|
protected |
Definition at line 355 of file analysis.py.
|
protected |
Definition at line 336 of file analysis.py.
|
protected |
Definition at line 348 of file analysis.py.
|
protected |
Definition at line 346 of file analysis.py.
|
protected |
Definition at line 503 of file analysis.py.
| tuple engine.pipeline.stability.analysis.ACOUSTIC_GATE_MODES = ("report_only", "nominal_phase", "worst_phase") |
Definition at line 246 of file analysis.py.