STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
test_ullage_dry_wall.py
Go to the documentation of this file.
1"""An ullage cools against the wall it touches: the dry wall above the liquid.
2
3A tank's ``wall_conductance`` is the whole tank's hA (a per-litre default, or the
4still-gas film over the full inner surface). Applied to the ullage at every
5fill, it let a 0.8 L ullage on a 95 % full LOX tank exchange heat with all
6fifteen litres of cold wall: a freshly pressed tank sat in Ready fell 548 -> 260
7psig in six seconds, where the stand takes something like thirty.
8``Tank(wall_by_level=True)`` (``Setup.ullage_wall_by_level``) scales it by the
9dry share of the wall. Checked against the geometry, and against the old
10behaviour where it is off.
11"""
12
13from __future__ import annotations
14
15import pytest
16
17from feedtwin.props import Fluid
18from feedtwin.session.burn import burn_setup
19from feedtwin.session.core import Setup
20from feedtwin.vessels import CylindricalTank, NoCollapse, Tank
21
22PSI = 6894.757293168361
23
24
25def _tank(by_level: bool) -> Tank:
26 return Tank(
27 Fluid("oxygen"),
28 Fluid("nitrogen"),
29 CylindricalTank(diameter=0.152, barrel_length=0.600),
30 collapse=NoCollapse(),
31 wall_mass=6.0,
32 wall_capacity=500.0,
33 wall_conductance=10.0,
34 wall_by_level=by_level,
35 )
36
37
38def _state(tank: Tank, fill: float): # type: ignore[no-untyped-def]
39 rho = tank.liquid.get("rho", T=90.0, q=0.0)
40 state = tank.initial_state(
41 pressure=548 * PSI,
42 liquid_mass=fill * tank.geometry.total_volume * rho,
43 liquid_temperature=90.0,
44 gas_temperature=300.0,
45 )
46 return state
47
48
50 tank = _tank(True)
51 fractions = [tank.dry_wall_fraction(_state(tank, f)) for f in (0.05, 0.4, 0.95)]
52 assert fractions == sorted(fractions, reverse=True)
53 assert fractions[0] > 0.9 and fractions[-1] < 0.15
54 # Against the geometry by hand: wall above the level over the whole wall.
55 g = tank.geometry
56 state = _state(tank, 0.4)
57 total = g.wetted_area(g.height)
58 assert tank.dry_wall_fraction(state) == pytest.approx(
59 (total - g.wetted_area(tank.level(state))) / total
60 )
61
62
64 """With nothing else exchanging, the ullage's energy rate is the wall term: on, it is
65 the off value times the dry fraction, exactly."""
66 off, on = _tank(False), _tank(True)
67 state = _state(off, 0.95)
68 rate_off = off.rates(state).ullage.energy
69 rate_on = on.rates(state).ullage.energy
70 assert rate_off < 0.0, "a 300 K ullage on a 90 K wall cools"
71 assert rate_on == pytest.approx(rate_off * on.dry_wall_fraction(state), rel=1e-9)
72 assert abs(rate_on) < 0.15 * abs(rate_off)
73
74
76 assert Setup().ullage_wall_by_level is True
77 assert burn_setup().ullage_wall_by_level is False
78 assert (
79 Tank(
80 Fluid("oxygen"),
81 Fluid("nitrogen"),
82 CylindricalTank(diameter=0.1, barrel_length=0.2),
83 ).wall_by_level
84 is False
85 )
_state(Tank tank, float fill)
None test_the_dry_fraction_is_the_wall_above_the_liquid()
Tank _tank(bool by_level)
None test_the_ullage_loses_heat_to_the_dry_wall_only()