STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
test_feed_exit_loss.py
Go to the documentation of this file.
1"""The feed line's velocity head is lost where it dumps into the injector manifold, and one
2flow area serves the loss model and the chug inertance alike.
3
4Exit loss. From a still tank to a still manifold,
5 P_tank - P_manifold = (K_entrance + f L/D + K_exit) q_line,
6and a line discharging into a plenum loses its whole velocity head: Borda-Carnot
7K = (1 - A_line/A_manifold)^2 -> 1, Crane TP-410 "pipe exit" K = 1.0. The shipped K0 values
8(scripts/feed_line_K.py) end at the last fitting, so P_injector was the stagnation pressure of
9flow still moving at ~15 m/s, and every orifice was credited one line q too much.
10
11Area. ``A_hydraulic`` is the passage; ``d_inlet`` used to win whenever it was set (it always
12is), so a twin line or non-circular passage lost 4x too much in performance while the chug
13model used the declared area.
14
15Expected values are hand arithmetic.
16"""
17from __future__ import annotations
18
19import math
20from pathlib import Path
21
22import pytest
23
24from engine.pipeline.config_schemas import FeedSystemConfig
25from engine.pipeline.feed_loss import delta_p_feed
26
27ROOT = Path(__file__).resolve().parents[1]
28PSI = 6894.757
29D_TUBE = 0.010922 # 1/2" x 0.035" tube bore
30A_TUBE = math.pi / 4.0 * D_TUBE ** 2
31D_NPT = 0.5 * 0.0254 # 1/2" NPT fitting through-bore
32
33
34@pytest.fixture(autouse=True, scope="module")
36 """The authoritative Python path; engine/accel mirrors it and test_numba_ab_parity holds the
37 two together."""
38 from engine import accel
39 real = accel.enabled, accel.require
40 accel.enabled = lambda: False
41 accel.require = lambda: False
42 try:
43 yield
44 finally:
45 accel.enabled, accel.require = real
46
47
48def _q(mdot, rho, A):
49 v = mdot / (rho * A)
50 return 0.5 * rho * v * v
51
52
54 cfg = FeedSystemConfig(line_size="1/2_TUBE_035", K0=2.019, K1=0.0)
55 assert cfg.K_exit == 1.0
56 assert delta_p_feed(1.118, 789.0, cfg, 4.0e6) == pytest.approx((2.019 + 1.0) * _q(1.118, 789.0, A_TUBE), rel=1e-12)
57
58
60 """Tube into a 1/2" NPT bore, then the dump: K at the tube is (A_tube/A_npt)^2 = (0.430/0.500)^4."""
61 cfg = FeedSystemConfig(line_size="1/2_TUBE_035", K0=0.643, K1=0.0, d_exit=D_NPT)
62 K_ref = (D_TUBE / D_NPT) ** 4
63 assert K_ref == pytest.approx(0.547, abs=1e-3)
64 assert delta_p_feed(1.68, 1140.0, cfg, 4.0e6) == pytest.approx((0.643 + K_ref) * _q(1.68, 1140.0, A_TUBE), rel=1e-12)
65
66
68 """Two 1/2" tubes: A = 2 x bore area. 1.118 kg/s of ethanol at K0 2.019 -> 6.61 psi, not 26.4."""
69 A2 = 2.0 * A_TUBE
70 cfg = FeedSystemConfig(line_size="1/2_TUBE_035", A_hydraulic=A2, K0=2.019, K1=0.0, K_exit=0.0)
71 dp = delta_p_feed(1.118, 789.0, cfg, 4.0e6)
72 assert dp == pytest.approx(2.019 * _q(1.118, 789.0, A2), rel=1e-12)
73 assert dp / PSI == pytest.approx(6.61, abs=0.01)
74
75
77 """feed_loss.py's own recipe: give A_hydraulic with d_inlet omitted."""
78 A2 = 2.0 * A_TUBE
79 cfg = FeedSystemConfig(A_hydraulic=A2, K0=2.019, K1=0.0, K_exit=0.0)
80 assert cfg.d_inlet == pytest.approx(math.sqrt(4.0 * A2 / math.pi), rel=1e-12)
81 assert delta_p_feed(1.118, 789.0, cfg, 4.0e6) == pytest.approx(2.019 * _q(1.118, 789.0, A2), rel=1e-12)
82
83
84def _evaluate(**feed):
85 from engine.pipeline.io import load_config
86 from engine.pipeline.config_schemas import PintleEngineConfig
87 from engine.core.runner import PintleEngineRunner
88 d = load_config(str(ROOT / "configs/ethalox_6500N.yaml")).model_dump()
89 for side in ("oxidizer", "fuel"):
90 d["feed_system"][side].update(feed)
91 cfg = PintleEngineConfig.model_validate(d)
92 P = 584.2669657943025 * PSI
93 return cfg, PintleEngineRunner(cfg).evaluate(P_tank_O=P, P_tank_F=P), P
94
95
97 cfg, r, P = _evaluate()
98 dg = r["diagnostics"]
99 rho = cfg.fluids["oxidizer"].density
100 q = _q(r["mdot_O"], rho, cfg.feed_system["oxidizer"].A_hydraulic)
101 K0 = cfg.feed_system["oxidizer"].K0
102 assert dg["P_injector_O"] == pytest.approx(P - (K0 + 1.0) * q, rel=2e-6)
103 _, r0, _ = _evaluate(K_exit=0.0)
104 assert r["Pc"] < r0["Pc"] and r["F"] < r0["F"]
test_exit_through_a_wider_fitting_is_referred_to_the_line()
test_injector_sees_the_manifold_not_the_line_stagnation()