STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
test_ullage_wall_t0.py
Go to the documentation of this file.
1"""The upper (ullage) wall's temperature at T-0 (``Setup.ullage_wall_T0_K``).
2
3``Session.prime`` builds a loaded tank's upper wall at the pressurant's 293.15 K.
4A LOX tank that has held its load has a cold upper shell, and that costs bottle
5(EngineDesign/docs/layerx/AUDIT.md D1). The setting moves only that wall, per
6tank; empty, the primed state is what it always was.
7
8The physics check is closed form: over a short hold with every valve shut, the
9extra cooling of the ullage gas is the wall's film, ``m cv dT = -hA (T_gas -
10T_wall) dt``, with the session's own ``hA`` -- the setting reaches the vessel the
11thermal model integrates, not just a field.
12"""
13
14from __future__ import annotations
15
16import json
17from pathlib import Path
18
19import pytest
20
21from feedtwin.pid import read_diagram
22from feedtwin.session import Setup, assemble_model, load_machine
23from feedtwin.session.burn import burn_setup, open_session
24from feedtwin.session.gauge import from_psig
25
26STAR = Path(__file__).resolve().parents[3]
27STAND = STAR / "feed-twin" / "backend" / "diagrams" / "ethalox_stand.json"
28TABLES = STAR / "feed-twin" / "backend" / "statemachines"
29
30pytestmark = pytest.mark.skipif(
31 not (STAND.exists() and TABLES.is_dir()), reason="stand drawing or tables absent"
32)
33
34
35def _primed(**setup): # type: ignore[no-untyped-def]
36 model = assemble_model(
37 read_diagram(json.loads(STAND.read_text()), name="ethalox_stand"),
38 diagram_id="ethalox_stand.json",
39 )
40 session = open_session(
41 model, load_machine(tables=TABLES), setup=burn_setup(**setup)
42 )
43 session.prime(tank_psi=550.0, copv_psi=4500.0, state="Ready")
44 return session
45
46
47def test_off_by_default() -> None:
48 assert dict(Setup().ullage_wall_T0_K) == {}
49 assert Setup().cryogen_ullage_wall_T0_K == 0.0
50
51
53 """Every tank exactly as ``Tank.initial_state`` built it before the setting."""
54 session = _primed()
55 for sim in session.tanks.values():
56 rho = sim.tank.liquid.get("rho", T=sim.state.liquid_temperature, q=0.0)
57 expected = sim.tank.initial_state(
58 pressure=from_psig(550.0),
59 liquid_mass=sim.tank.geometry.total_volume * 0.95 * rho,
60 liquid_temperature=sim.state.liquid_temperature,
61 gas_temperature=293.15,
62 contact_time=300.0,
63 split_wall=True,
64 )
65 assert sim.state == expected, sim.id
66 assert not any("upper wall at T-0" in note for note in session.assumptions)
67
68
70 base = _primed()
71 cold = _primed(ullage_wall_T0_K={"OXT": 150.0})
72 lox, lox0 = cold.tanks["OXT"].state, base.tanks["OXT"].state
73 assert lox.ullage.wall_temperature == 150.0
74 assert lox.ullage.mass == lox0.ullage.mass
75 assert lox.ullage.energy == lox0.ullage.energy
76 assert lox.wetted_wall_temperature == lox0.wetted_wall_temperature
77 assert cold.tanks["FUT"].state == base.tanks["FUT"].state
78 assert any("TK-LOX" in n or "upper wall" in n for n in cold.assumptions)
79
80
82 dial = _primed(cryogen_ullage_wall_T0_K=170.0)
83 assert dial.tanks["OXT"].state.ullage.wall_temperature == 170.0
84 # The fuel tank holds ethanol at room temperature: not a cryogen.
85 assert dial.tanks["FUT"].state.ullage.wall_temperature == 293.15
86 both = _primed(cryogen_ullage_wall_T0_K=170.0, ullage_wall_T0_K={"OXT": 120.0})
87 assert both.tanks["OXT"].state.ullage.wall_temperature == 120.0
88
89
91 """0.1 s shut in, wall at 150 K against gas at 293 K: the gas cools by
92 hA mean(T_gas - T_wall) t / (m cv) more than with the warm wall."""
93 hold, step = 0.1, 0.02
94 warm, cold = _primed(), _primed(ullage_wall_T0_K={"OXT": 150.0})
95 sim = cold.tanks["OXT"]
96 start = sim.state
97 T0 = sim.tank.gas_temperature(start)
98 cv = sim.tank.gas.get("cv", p=sim.pressure, T=T0)
99 for session in (warm, cold):
100 for _ in range(int(round(hold / step))):
101 session.step(step)
102 T_warm = warm.tanks["OXT"].tank.gas_temperature(warm.tanks["OXT"].state)
103 T_cold = sim.tank.gas_temperature(sim.state)
104 gap = 0.5 * (
105 (T0 - start.ullage.wall_temperature)
106 + (T_cold - sim.state.ullage.wall_temperature)
107 )
108 hand = sim.tank.wall_conductance * gap * hold / (start.ullage.mass * cv)
109 assert T_warm - T_cold == pytest.approx(hand, rel=0.05)
110 # And the tank sags: the gas it holds is colder.
111 assert cold.tanks["OXT"].pressure < warm.tanks["OXT"].pressure - 5.0 * 6894.757
None test_a_cold_upper_wall_cools_the_ullage_at_its_film_rate()
None test_the_cryogen_dial_and_the_per_tank_map()
None test_default_prime_is_the_old_initial_state()