STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
test_tank_runs_dry.py
Go to the documentation of this file.
1"""A tank gives what it holds, and books what it was asked for beyond that.
2
3``TankSim.advance`` used to stop the outflow altogether once a tank was down
4to a gram, while the network that asked for it went on delivering it: up to a
5step of propellant the engine burned and no vessel gave. The session now ends
6a coupling step where a tank runs out (``Session._dry_cut``); this is the
7vessel's backstop under it. Checked against the arithmetic of the inputs:
8what left the tank plus what was booked is what was asked for.
9"""
10
11from __future__ import annotations
12
13from dataclasses import replace
14
15import pytest
16
17from feedtwin.props import Fluid
18from feedtwin.session.core import DRY_MASS, TankSim
19from feedtwin.session.gauge import from_psig
20from feedtwin.vessels import CylindricalTank, Tank, TankState
21
22
23def _sim(liquid_kg: float) -> TankSim:
24 tank = Tank(
25 Fluid("ethanol"),
26 Fluid("nitrogen"),
27 CylindricalTank(diameter=0.152, barrel_length=0.40),
28 )
29 state = tank.initial_state(
30 pressure=from_psig(400.0),
31 liquid_mass=4.0,
32 liquid_temperature=293.15,
33 gas_temperature=293.15,
34 )
35 return TankSim(
36 id="T",
37 label="T",
38 tank=tank,
39 state=replace(state, liquid_mass=liquid_kg),
40 ullage_node="u",
41 outlet_node="o",
42 )
43
44
45def _held(state: TankState) -> float:
46 return state.liquid_mass + state.ullage.mass + state.vapour_mass
47
48
49def _drain(sim: TankSim, dt: float, mdot: float) -> float:
50 """Advance with only a liquid outflow; return the mass that left [kg]."""
51 before = _held(sim.state)
52 sim.advance(
53 dt,
54 mdot_liquid_out=mdot,
55 mdot_gas_in=0.0,
56 mdot_gas_out=0.0,
57 enthalpy_gas_in=sim.tank.gas_enthalpy(sim.state),
58 )
59 return before - _held(sim.state)
60
61
63 sim = _sim(0.005)
64 dt, mdot = 0.02, 1.0
65 left = _drain(sim, dt, mdot)
66 assert sim.state.liquid_mass == pytest.approx(0.0, abs=1e-12)
67 assert left == pytest.approx(0.005, rel=1e-9)
68 assert left + sim.fixed_kg == pytest.approx(mdot * dt, rel=1e-9)
69
70
72 """Below DRY_MASS the tank is empty to the panel, but what it holds still
73 flows: zeroing it -- what this did -- refused the step without booking."""
74 sim = _sim(0.5 * DRY_MASS)
75 dt, mdot = 1e-3, 0.1
76 left = _drain(sim, dt, mdot)
77 assert sim.empty
78 assert left == pytest.approx(mdot * dt, rel=1e-9)
79 assert sim.fixed_kg == pytest.approx(0.0, abs=1e-12)
80
81
83 sim = _sim(2.0)
84 dt, mdot = 0.02, 1.0
85 left = _drain(sim, dt, mdot)
86 assert not sim.empty
87 assert left == pytest.approx(mdot * dt, rel=1e-9)
88 assert sim.fixed_kg == pytest.approx(0.0, abs=1e-12)
TankSim _sim(float liquid_kg)
None test_the_last_gram_is_delivered_not_dropped()
None test_a_tank_with_enough_is_untouched()
float _held(TankState state)
None test_asked_for_more_than_it_holds_it_gives_all_and_books_the_rest()
float _drain(TankSim sim, float dt, float mdot)