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
2
flow area serves the loss model and the chug inertance alike.
3
4
Exit loss. From a still tank to a still manifold,
5
P_tank - P_manifold = (K_entrance + f L/D + K_exit) q_line,
6
and a line discharging into a plenum loses its whole velocity head: Borda-Carnot
7
K = (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
9
flow still moving at ~15 m/s, and every orifice was credited one line q too much.
10
11
Area. ``A_hydraulic`` is the passage; ``d_inlet`` used to win whenever it was set (it always
12
is), so a twin line or non-circular passage lost 4x too much in performance while the chug
13
model used the declared area.
14
15
Expected values are hand arithmetic.
16
"""
17
from
__future__
import
annotations
18
19
import
math
20
from
pathlib
import
Path
21
22
import
pytest
23
24
from
engine.pipeline.config_schemas
import
FeedSystemConfig
25
from
engine.pipeline.feed_loss
import
delta_p_feed
26
27
ROOT = Path(__file__).resolve().parents[1]
28
PSI = 6894.757
29
D_TUBE = 0.010922
# 1/2" x 0.035" tube bore
30
A_TUBE = math.pi / 4.0 * D_TUBE ** 2
31
D_NPT = 0.5 * 0.0254
# 1/2" NPT fitting through-bore
32
33
34
@pytest.fixture(autouse=True, scope="module")
35
def
_python_physics
():
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
48
def
_q
(mdot, rho, A):
49
v = mdot / (rho * A)
50
return
0.5 * rho * v * v
51
52
53
def
test_exit_loss_defaults_to_one_line_velocity_head
():
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
59
def
test_exit_through_a_wider_fitting_is_referred_to_the_line
():
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
67
def
test_twin_line_area_is_used
():
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
76
def
test_area_alone_is_a_valid_feed_passage
():
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
84
def
_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
96
def
test_injector_sees_the_manifold_not_the_line_stagnation
():
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"
]
engine.pipeline.config_schemas.FeedSystemConfig
Definition
config_schemas.py:309
engine.core.runner
Definition
runner.py:1
engine.pipeline.config_schemas
Definition
config_schemas.py:1
engine.pipeline.feed_loss
Definition
feed_loss.py:1
engine.pipeline.io
Definition
io.py:1
test_feed_exit_loss._evaluate
_evaluate(**feed)
Definition
test_feed_exit_loss.py:84
test_feed_exit_loss._python_physics
_python_physics()
Definition
test_feed_exit_loss.py:35
test_feed_exit_loss._q
_q(mdot, rho, A)
Definition
test_feed_exit_loss.py:48
test_feed_exit_loss.test_exit_loss_defaults_to_one_line_velocity_head
test_exit_loss_defaults_to_one_line_velocity_head()
Definition
test_feed_exit_loss.py:53
test_feed_exit_loss.test_exit_through_a_wider_fitting_is_referred_to_the_line
test_exit_through_a_wider_fitting_is_referred_to_the_line()
Definition
test_feed_exit_loss.py:59
test_feed_exit_loss.test_twin_line_area_is_used
test_twin_line_area_is_used()
Definition
test_feed_exit_loss.py:67
test_feed_exit_loss.test_injector_sees_the_manifold_not_the_line_stagnation
test_injector_sees_the_manifold_not_the_line_stagnation()
Definition
test_feed_exit_loss.py:96
test_feed_exit_loss.test_area_alone_is_a_valid_feed_passage
test_area_alone_is_a_valid_feed_passage()
Definition
test_feed_exit_loss.py:76
EngineDesign
tests
test_feed_exit_loss.py
Generated by
1.15.0