STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
test_vaporization_card.py
Go to the documentation of this file.
1"""The stability tab's vaporization card draws the droplet march that sets eta_vap, not a
2model of its own.
3
4It used to show L_vap = u_inj x tau_conv: injection speed held down the whole chamber, times the
5chug lag (which on the Leonardi model includes a mixing lag). On the 6.5 kN ethalox doublet that
6read 675 mm in a 199 mm chamber while the c* model had the fuel 95 % vaporized at 157 mm.
7"""
8import copy
9
10import pytest
11
12PSI = 6894.757
13CFG = "configs/ethalox_6500N.yaml"
14
15
16@pytest.fixture(scope="module")
17def run():
18 from engine.pipeline.io import load_config
19 from engine.core.runner import PintleEngineRunner
20 cfg = load_config(CFG)
21 return PintleEngineRunner(copy.deepcopy(cfg)).evaluate(
22 cfg.lox_tank.initial_pressure_psi * PSI, cfg.fuel_tank.initial_pressure_psi * PSI,
23 silent=True, rich_stability=True)
24
25
27 ce = run["diagnostics"]["cstar_efficiency"]
28 vap = run["stability_rich"]["vaporization"]
29 by = {s["stream"]: s for s in vap["streams"]}
30 assert vap["L_ch_m"] == pytest.approx(ce["L_chamber_equiv"], rel=1e-12)
31 for k in ("O", "F"):
32 assert by[k]["frac_vaporized_end"] == pytest.approx(ce[f"frac_vaporized_{k}"], rel=1e-9)
33 if ce[f"x_vap95_{k}"] is not None:
34 assert by[k]["L_vap_m"] == pytest.approx(ce[f"x_vap95_{k}"] + ce["x_drop_formation"], rel=1e-9)
35 prof = by[k]["remaining_profile"]
36 assert prof[0] == [0.0, 1.0] # all liquid at the face
37 assert prof[-1][0] == pytest.approx(ce["L_chamber_equiv"], rel=1e-9)
38 assert prof[-1][1] == pytest.approx(1.0 - ce[f"frac_vaporized_{k}"], abs=1e-9)
39 assert all(a[1] >= b[1] - 1e-12 for a, b in zip(prof, prof[1:])) # never re-condenses
40
41
43 vap = run["stability_rich"]["vaporization"]
44 lead = next(s for s in vap["streams"] if s["stream"] == vap["rate_limiting_stream"])
45 u = run["diagnostics"][f"v_{lead['stream']}_bulk"]
46 assert lead["L_vap_m"] != pytest.approx(u * lead["tau_conv_s"], rel=0.05)
47
48
50 """profile_points > 0 runs the Python march; the solver's (compiled) path must give the same."""
51 from engine.pipeline.combustion_physics import spray_vaporization_march
52 streams = [{"name": "O", "mass_fraction": 0.6, "D32": 90e-6, "rho_l": 1100.0, "cp_l": 1700.0,
53 "T0": 90.0, "T_s": 140.0, "h_fg": 1.3e5},
54 {"name": "F", "mass_fraction": 0.4, "D32": 150e-6, "rho_l": 750.0, "cp_l": 2600.0,
55 "T0": 293.0, "T_s": 460.0, "h_fg": 5.4e5}]
56 kw = dict(Pc=2.6e6, Tc=3200.0, gamma=1.14, R=350.0, m_dot_total=3.0, Ac=0.0127, L_chamber=0.18,
57 u_drop0=25.0, rr_q=3.0)
58 a = spray_vaporization_march(streams, **kw)
59 b = spray_vaporization_march(streams, **kw, profile_points=40)
60 assert "profile" not in a and len(b["profile"]["F"]) > 20
61 for n in ("O", "F"):
62 assert b["frac_vaporized"][n] == pytest.approx(a["frac_vaporized"][n], rel=1e-9)
63 assert b["profile"]["F"][-1][1] == pytest.approx(b["frac_vaporized"]["F"], rel=1e-12)
64
65
67 from engine.pipeline.stability.report import _radar, _vaporization_profile
68 march = {"L_chamber": 0.2, "x_drop_formation": 0.01, "streams": {
69 "O": {"instant": False, "x95": 0.05, "frac_end": 1.0, "profile": [[0.0, 0.0], [0.2, 1.0]]},
70 "F": {"instant": False, "x95": None, "frac_end": 0.9, "profile": [[0.0, 0.0], [0.2, 0.9]]}}}
71 inp = {"D32_O": 9e-5, "D32_F": 1.5e-4, "tau_conv_O": 0.01, "tau_conv_F": 0.02, "tau_sens": 0.003}
72 vap = _vaporization_profile(inp, 2.6e6, march=march)
73 assert vap["rate_limiting_stream"] == "F" and vap["L_vap_m"] is None
74 assert vap["vaporized_in_chamber"] is False
75 ac = {"modes": []}
76 assert _radar(1.5, ac, vap, 1.05)["values"][3] == pytest.approx(0.9 / 0.95)