STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
test_jump_to_t0.py
Go to the documentation of this file.
1"""The cockpit's Jump to T-0: loaded, charged and at the regulators' lockup.
2
3Checked against the drawing, not the code: the regulator drawn at 560 psi
4(gauge, as a drawing reads) locks the tanks up at 560 plus its seat's rise,
5and that is where T-0 puts them -- in Ready, loaded, with the bottle charged.
6"""
7
8from __future__ import annotations
9
10import pytest
11from test_press_path_coupling import _helium_stand
12
13from feedtwin.session.burn import jump_to_t0, regulator_lockup
14from feedtwin.session.gauge import from_psig, psig
15
16
18 session = _helium_stand()
19 regulator = next(
20 b.component
21 for b in session.model.built.network.branches.values()
22 if type(b.component).__name__.endswith("Regulator")
23 )
24 rise = float(regulator.p.get("lockup_rise", 0.0))
25 for tank_id in session.tanks:
26 lockup = regulator_lockup(session, tank_id)
27 assert lockup is not None
28 assert lockup == pytest.approx(from_psig(560.0) + rise, abs=200.0)
29
30
32 session = _helium_stand()
33 t0 = jump_to_t0(session, copv_psi=4500.0, fill_fraction=0.9)
34 assert session.state == "Ready"
35 assert set(t0.lockup_psi) == set(session.tanks)
36 for sim in session.tanks.values():
37 assert psig(sim.pressure) == pytest.approx(t0.tank_psi, abs=0.5)
38 assert sim.state.liquid_mass > 0.5
39 assert t0.tank_psi == pytest.approx(
40 psig(regulator_lockup(session, next(iter(session.tanks))) or 0.0), abs=0.5
41 )
42 bottle = next(iter(session.bottles.values()))
43 assert psig(bottle.pressure) == pytest.approx(4500.0, abs=5.0)
44
45
47 """The console reads each tank's lockup on every tick. Evaluated through
48 the step's signals, that snapped every valve to its command: a main
49 halfway through its travel was fully open after the readout, so the
50 console's valves opened in one tick whatever their travel time."""
51 session = _helium_stand()
52 jump_to_t0(session, copv_psi=4500.0, fill_fraction=0.9)
53 session.command_state("Fire")
54 travel = min(session._travel_time(v) for v in session.model.built.actuators)
55 session.step(travel / 4)
56 moving = {v: x for v, x in session._positions.items() if 0.0 < x < 1.0}
57 assert moving, "a valve should be mid-travel a quarter of the way in"
58 tank_id = next(iter(session.tanks))
59 for loaded in (False, True):
60 regulator_lockup(session, tank_id, loaded_dome=loaded)
61 assert {v: session._positions[v] for v in moving} == moving
62
63
65 """A regulator delivers no more than its inlet. A bottle charged under the
66 lockup leaves the regulator wide open and the tanks where the bottle is: by
67 hand, 200 psig of helium presses the tanks to at most 200 psig. T-0 primed
68 them at the 560 psig the regulator's law gives, from gas the bottle never
69 had (LE4 (3), COPV 400 psig: tanks at 579 psig)."""
70 session = _helium_stand()
71 t0 = jump_to_t0(session, copv_psi=200.0, fill_fraction=0.9)
72 bottle = next(iter(session.bottles.values()))
73 assert psig(bottle.pressure) == pytest.approx(200.0, abs=1.0)
74 for sim in session.tanks.values():
75 assert psig(sim.pressure) <= psig(bottle.pressure) + 0.5
76 assert psig(sim.pressure) == pytest.approx(200.0, abs=1.0)
77 assert t0.tank_psi == pytest.approx(200.0, abs=1.0)
78 # The regulator's own lockup is still reported, and the note says why the
79 # tanks are not at it.
80 assert all(v > 500.0 for v in t0.lockup_psi.values())
81 assert any("wide open" in n for n in t0.notes)
82
83
85 monkeypatch: pytest.MonkeyPatch,
86) -> None:
87 """Two regulators locking up 20 psi apart over a 200 psig bottle. The first
88 note said "every tank was primed at 574.7 psia" -- the lower lockup -- and
89 the next that they were primed at the bottle. They went to the bottle, and
90 both notes say so."""
91 import feedtwin.session.burn as burn
92
93 session = _helium_stand()
94 first, second = session.vehicle_tanks
95 apart = {first: from_psig(560.0), second: from_psig(580.0)}
96 monkeypatch.setattr(
97 burn, "regulator_lockup", lambda _s, tank_id, *_a, **_k: apart[tank_id]
98 )
99 t0 = jump_to_t0(session, copv_psi=200.0, fill_fraction=0.9)
100 assert t0.tank_psi == pytest.approx(200.0, abs=1.0)
101 (spread,) = [n for n in t0.notes if "lock up at" in n]
102 assert spread.endswith("every tank was primed at 214.7 psia."), spread
103 assert any("wide open" in n for n in t0.notes)
104
105
107 """Dome 735 on LE4: both tanks lock up at ~745 psia, over oxygen's 731 psia
108 critical pressure, and Ready said "LOX-Tank is at its propellant's critical
109 pressure and the model can go no higher. The drawing has no relief valve" --
110 with the tank above it, and a relief drawn. 90 K LOX under nitrogen is an
111 ordinary compressed liquid; what nears the critical point is the propellant
112 itself, a liquid warmed toward oxygen's 154.6 K."""
113 from dataclasses import replace
114
115 from test_ignore_gse import _session as _le4
116
117 session = _le4(True)
118 session.setup = replace(session.setup, dome_psi=735.0)
119 jump_to_t0(session, copv_psi=3750.0, fill_fraction=0.95)
120 lox = next(
121 sim for sim in session.tanks.values() if sim.state.liquid_temperature < 120.0
122 )
123 p_crit = float(lox.tank.liquid.critical_pressure)
124 assert lox.pressure > p_crit, "the total pressure is over oxygen's critical"
125 notes = session.step(0.02).notes
126 assert not [n for n in notes if "critical" in n], notes
127 # A liquid that has warmed to within a hair of its critical point is (a
128 # kilogram of it: the load at 154 K would not fit the tank).
129 lox.state = replace(lox.state, liquid_temperature=154.0, liquid_mass=1.0)
130 (near,) = [n for n in session._notes() if "critical" in n]
131 assert near.startswith("LOX-Tank") and "Vent it." in near
132 assert "can go no higher" not in near
133 assert session._reliefs_on(lox.id), "LE4 draws a relief on the LOX tank"
134 assert "relief" not in near
135 # Without the LOX tank's own relief the note says so, though the COPV and
136 # the fuel tank keep theirs: neither lifts for this tank.
137 session._reliefs = [
138 (b, branch)
139 for b, branch in session._reliefs
140 if b not in dict(session._reliefs_on(lox.id))
141 ]
142 assert session._reliefs, "the other reliefs are still drawn"
143 (bare,) = [n for n in session._notes() if "critical" in n]
144 assert "No relief valve is drawn on LOX-Tank" in bare, bare
145
146
148 """A dome turned to zero gives dome + bias - S x bottle under atmosphere on a
149 charged COPV: the regulator is shut, and no regulator pulls a vacuum. T-0
150 primed the tanks at 9.6 psia on LE4 (3)."""
151 from dataclasses import replace
152
153 from test_ignore_gse import _session as _le4
154
155 session = _le4(True)
156 session.setup = replace(session.setup, dome_psi=0.0)
157 t0 = jump_to_t0(session, copv_psi=3750.0, fill_fraction=0.95)
158 assert all(v < 0.0 for v in t0.lockup_psi.values()), "under atmosphere"
159 for tank_id in session.vehicle_tanks:
160 assert psig(session.tanks[tank_id].pressure) == pytest.approx(0.0, abs=0.05)
161 assert t0.tank_psi == pytest.approx(0.0, abs=0.05)
162 assert any("shut" in n for n in t0.notes)
#define min(a, b)
Definition Arduino.h:42
None test_reading_the_lockup_moves_nothing()
None test_the_lockup_is_the_drawn_regulator_at_zero_flow()
None test_subcooled_lox_over_its_critical_pressure_is_not_critical()
None test_t0_is_loaded_charged_and_at_lockup_in_ready()
None test_a_bottle_under_the_lockup_primes_the_tanks_at_the_bottle()
None test_regulators_apart_over_a_low_bottle_say_where_the_tanks_went(pytest.MonkeyPatch monkeypatch)
None test_a_lockup_under_atmosphere_primes_the_tanks_at_atmosphere()