|
STAR
Cal STAR — firmware, DAQ server, and engine design
|
Classes | |
| class | StreamThermo |
| class | ChamberThermo |
| class | LagBreakdown |
Functions | |
| float | atomization_lag (StreamThermo st, ChamberThermo ch) |
| float | evaporation_constant_leonardi (float MR, float T_inf, float T_crit) |
| float | convection_correction_leonardi (float Pc_bar) |
| float | ranz_marshall_correction (float Re_d, float Pr=0.7) |
| float | _slip_reynolds (StreamThermo st, ChamberThermo ch, float mu_g=7.0e-5) |
| float | vaporization_lag_leonardi (StreamThermo st, ChamberThermo ch, *, str convection=DEFAULT_CONVECTION_MODEL) |
| Tuple[float, float] | vaporization_lag_d2 (StreamThermo st, ChamberThermo ch) |
| float | resolve_mixing_lag (float tau_vap_liquid, float mix_fraction) |
| _ModelResult | _model_d2_law (StreamThermo st, ChamberThermo ch, str convection) |
| _ModelResult | _model_leonardi (StreamThermo st, ChamberThermo ch, str convection) |
| Dict[str, LagBreakdown] | compute_lags (Dict[str, StreamThermo] streams, ChamberThermo ch, *, str model="d2_law", float mix_fraction=0.0, str convection=DEFAULT_CONVECTION_MODEL, Optional[Callable[[str, float, str, str], float]] on_fallback=None) |
Variables | |
| list | __all__ |
| float | MASS_HALF_LIFE_FRACTION = float(1.0 - 0.5 ** (2.0 / 3.0)) |
| dict | CONVECTION_MODELS |
| str | DEFAULT_CONVECTION_MODEL = "none" |
| _ModelResult = Tuple[float, float, float, float, Tuple[str, ...]] | |
| dict | TIME_LAG_MODELS |
Conversion time lags for the chug loop — a registry of NAMED models.
The chug characteristic equation (``chug.py``) needs one number per propellant stream: the lag
between an injection-rate perturbation and the heat release it produces. That number is where the
propellant and the injector enter the stability problem, so it is the one place that must not
hardcode either.
Two models, both selectable through ``StabilityConfig.time_lag_model``:
``d2_law``
The historical STAR model: ``tau = D32**2 / K_v`` with the Godsave/Spalding evaporation
constant. This is the **quiescent** droplet lifetime — no convection, no atomization, no
mixing — and it is reproduced here bit-for-bit so old results stay reproducible.
``leonardi_dtl``
The double-time-lag decomposition of Leonardi, Nasuti, Di Matteo & Steelant, *"A methodology
to study the possible occurrence of chugging in liquid rocket engines during transient
start-up"*, Acta Astronautica 139 (2017) 344-356 [hereafter **L17**]:
tau_tot = tau_atom + tau_vap + tau_mix (L17 eq. 5)
with a convection-corrected vaporization lag (eq. 8-9) and an atomization lag (eq. 6-7). The
decisive structural point is **phase**: L17 §3.2 gives the gaseous propellant *only* the mixing
lag, because a gas neither atomizes nor vaporizes. STAR's previous code ran the d^2-law on both
streams unconditionally, which silently invents a droplet lifetime for a gas.
What is deliberately NOT implemented
------------------------------------
L17 eq. 10 (the initial droplet diameter ``D0``) is a correlation "specifically developed for
coaxial injectors and liquid oxygen". EngineDesign already solves a Sauter mean diameter with the
injector-appropriate model — Ingebo for impinging, Lefebvre for coaxial, the pintle sheet model for
pintle — so ``D0`` is taken from that solve. Adopting eq. 10 would hardcode *one* injector and *one*
oxidizer into a multi-injector, multi-propellant tool, which is precisely the coupling this module
exists to remove. (It is also not dimensionally closed as printed: the exponents 2.25 and -2.65 do
not cancel, so its units depend on ref. [24] and cannot be reconstructed from L17 alone.)
The convection correction (L17 eq. 8) is OFF by default — and why
-----------------------------------------------------------------
L17 eq. 8 divides the quiescent droplet lifetime by ``1 + 1.5*alpha``, ``alpha = 1 - 3e-3*pc[bar]``.
Applying it makes the model *worse* against the paper's own experiment, so it ships behind a named
switch set to ``"none"``. The evidence (``scripts/chug_timelag_benchmark.py``, benchmarks B and E,
on the GH2/LOX rig of L17 ref. [25]):
* Eq. 9's evaporation constant in the QUIESCENT form, ``tau_vap = D0**2 / k``, gives 4.98 ms at
L17's own reference point (D0 = 83 um, MR 5, 44.8 bar, 2038 K) against the experiment-derived
4.4 ms — **+13 %**. Apply eq. 8 and it becomes 2.17 ms, **-51 %**.
* End-to-end through ``chug.py``, quiescent eq. 9 predicts 53 Hz and a stability boundary at
Delta_p_ox/pc = 0.30 against a measured 66 Hz and 0.35. With eq. 8 it is 104 Hz and 0.20.
* Eq. 8 also disagrees with Ranz-Marshall in *trend*, not just magnitude: it depends on chamber
pressure alone — no slip velocity, no drop size — and it FALLS as Pc rises, while the physical
correction does not.
The coherent reading is that eq. 9's ``k`` was already calibrated against real chamber data (L17
routes its 4.4 ms through Priem-Heidmann's L50/v_inj), so it *contains* the convective enhancement
and eq. 8 double-counts it. That also reconciles L17's two otherwise-inconsistent statements about
the same working point. Both corrections remain available through ``CONVECTION_MODELS`` so the run
report can say which one produced the answer.
|
protected |
-> (tau_atom, tau_vap, K_v, tau_mix_basis, notes). tau_mix is applied by ``compute_lags``. ``convection`` is accepted and ignored: the d^2-law is the historical model and is reproduced unchanged, corrections included (there were none).
Definition at line 343 of file timelag.py.
References vaporization_lag_d2().
|
protected |
Definition at line 356 of file timelag.py.
References atomization_lag(), vaporization_lag_d2(), and vaporization_lag_leonardi().
|
protected |
Droplet Reynolds number on the gas-droplet slip velocity. Used only by ``ranz_marshall``.
Definition at line 245 of file timelag.py.
| float engine.pipeline.stability.timelag.atomization_lag | ( | StreamThermo | st, |
| ChamberThermo | ch ) |
Atomization lag [s]. **L17 eq. 6-7** (after Boronine, Vollmer & Frey, ref. [23]):
tau_atom = 6e-4 * (rho_g/rho_l)^-0.32 * We_g^0.03 * Re_l^0.55 * D_l/u_l
Re_l = u_l D_l rho_l / mu_l
We_g = 2 rho_g (u_g - u_l)^2 D_l / sigma_l
Returns 0.0 for a gas stream (nothing to atomize) and NaN when an input is missing, so a caller
that cannot supply injector geometry gets a recorded fallback rather than a fabricated lag.
Definition at line 169 of file timelag.py.
Referenced by _model_leonardi().
| Dict[str, LagBreakdown] engine.pipeline.stability.timelag.compute_lags | ( | Dict[str, StreamThermo] | streams, |
| ChamberThermo | ch, | ||
| * | , | ||
| str | model = "d2_law", | ||
| float | mix_fraction = 0.0, | ||
| str | convection = DEFAULT_CONVECTION_MODEL, | ||
| Optional[Callable[[str, float, str, str], float]] | on_fallback = None ) |
Lag breakdown for every stream under one named model. ``mix_fraction`` scales the shared mixing lag off the SLOWEST liquid stream's vaporization lag (the rate-limiting one — L17 assigns the same tau_mix to both propellants). Pass 0.0 to disable it, which is what ``d2_law`` does by default so it reproduces the historical numbers exactly. ``on_fallback(name, value, unit, reason) -> value`` is the assumptions hook; the integration layer passes ``assumptions.assume`` so nothing is substituted silently. Defaults to identity for pure-numeric use (tests, the benchmark script).
Definition at line 388 of file timelag.py.
References max, and resolve_mixing_lag().
| float engine.pipeline.stability.timelag.convection_correction_leonardi | ( | float | Pc_bar | ) |
L17 eq. 8 convective speed-up factor ``1 + 1.5*alpha`` with ``alpha = 1 - 3e-3*pc[bar]``. ``tau_vap = tau_vap(Re=0) / (1 + 1.5*alpha)`` — a droplet in a crossflow lives shorter than a quiescent one. Note the factor FALLS with chamber pressure (alpha -> 0 near 333 bar), i.e. the correlation says the convective enhancement washes out at high Pc. Floored at 1.0 so the correction can never *lengthen* the lag past the quiescent value.
Definition at line 219 of file timelag.py.
References max.
| float engine.pipeline.stability.timelag.evaporation_constant_leonardi | ( | float | MR, |
| float | T_inf, | ||
| float | T_crit ) |
L17 eq. 9 evaporation constant ``k`` [m^2/s]:
k = 1e-6 * [ 1.01/(1 + MR) + 1.16e-3 (T_inf - T_cr)^0.93 ]^0.86
``T_inf`` is the combustion-gas temperature [K] and ``T_cr`` the LIQUID critical temperature
[K] — a propellant property, which is why it is a per-stream input here and not a constant.
Definition at line 196 of file timelag.py.
Referenced by vaporization_lag_leonardi().
| float engine.pipeline.stability.timelag.ranz_marshall_correction | ( | float | Re_d, |
| float | Pr = 0.7 ) |
Textbook convective correction ``Nu/2 = 1 + 0.3 Re_d^0.5 Pr^(1/3)`` (Ranz-Marshall). Not used by any model — it is the independent yardstick the benchmark scores L17 eq. 8 against, so a disagreement shows up as a number instead of an assumption. ``Re_d`` is the droplet Reynolds number based on the slip velocity and the drop diameter.
Definition at line 233 of file timelag.py.
| float engine.pipeline.stability.timelag.resolve_mixing_lag | ( | float | tau_vap_liquid, |
| float | mix_fraction ) |
Mixing lag [s] shared by all streams, as a fraction of the rate-limiting vaporization lag. **Why a fraction and not L17 fig. 1.** The paper reads tau_mix off Szuch's empirical curve of mixing time versus L50 (the length to vaporize 50% of the liquid, NASA TN-D-7026). That curve is a figure, not a table, and is not reproduced here; digitizing it by eye would be inventing a correlation. What L17 *does* state numerically is its own calibration point — tau_vap = 4.4 ms and tau_mix = 2.2 ms for the validation engine (L17 §3.1), i.e. a ratio of 0.5 — and L50 is itself proportional to tau_vap at fixed droplet speed (``MASS_HALF_LIFE_FRACTION``), so a constant of proportionality is the faithful reduction of the curve to one number. The default 0.5 therefore carries the paper's provenance, and the caller records it through the assumptions registry. Swap in a digitized curve by replacing this function, not by tuning 0.5.
Definition at line 315 of file timelag.py.
Referenced by compute_lags().
| Tuple[float, float] engine.pipeline.stability.timelag.vaporization_lag_d2 | ( | StreamThermo | st, |
| ChamberThermo | ch ) |
Quiescent d^2-law lag [s] and its evaporation constant K_v — STAR's historical model. Exactly ``core.lags_from_smd(..., chi=1.0)``: same call, same arguments, same order, so the ``d2_law`` branch is bit-for-bit what the code did before this module existed.
Definition at line 296 of file timelag.py.
Referenced by _model_d2_law(), and _model_leonardi().
| float engine.pipeline.stability.timelag.vaporization_lag_leonardi | ( | StreamThermo | st, |
| ChamberThermo | ch, | ||
| * | , | ||
| str | convection = DEFAULT_CONVECTION_MODEL ) |
Vaporization lag [s] from **L17 eq. 9**'s evaporation constant: ``tau = D0**2 / k / factor``. ``convection`` names an entry of ``CONVECTION_MODELS``; the default ``"none"`` leaves the quiescent form, which is the variant that matches the experiment (module docstring). 0.0 for a gas stream.
Definition at line 267 of file timelag.py.
References evaporation_constant_leonardi().
Referenced by _model_leonardi().
|
private |
Definition at line 69 of file timelag.py.
|
protected |
Definition at line 340 of file timelag.py.
| dict engine.pipeline.stability.timelag.CONVECTION_MODELS |
Definition at line 256 of file timelag.py.
| str engine.pipeline.stability.timelag.DEFAULT_CONVECTION_MODEL = "none" |
Definition at line 264 of file timelag.py.
| float engine.pipeline.stability.timelag.MASS_HALF_LIFE_FRACTION = float(1.0 - 0.5 ** (2.0 / 3.0)) |
Definition at line 92 of file timelag.py.
| dict engine.pipeline.stability.timelag.TIME_LAG_MODELS |
Definition at line 382 of file timelag.py.