STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
test_timeseries_fill_levels.py
Go to the documentation of this file.
1"""Time-Series tank fill levels start from the configured load, and a curve that needs more says so.
2
3They used to start from the mass the curve consumes, so every run ended at exactly 0: on the LE4
4(3) stand's engine at 578/578 psia for the config's 3.994 s the chart drew 7.55 kg of LOX for a
5tank loaded with 6.61 kg (lox_tank.mass, the fire load), while the Flight tab on the same series
6said the LOX runs dry at 3.50 s. Hand check: 6.611 kg / 1.8755 kg/s = 3.525 s.
7"""
8
9from __future__ import annotations
10
11import types
12
13import numpy as np
14import pytest
15
16from backend.routers import timeseries as ts
17
18
19class _Runner:
20 def __init__(self, lox_load, fuel_load, mdot_O=1.8755, mdot_F=1.2451):
21 self.config = types.SimpleNamespace(
22 ablative_cooling=None, press_tank=None,
23 lox_tank=types.SimpleNamespace(mass=lox_load), fuel_tank=types.SimpleNamespace(mass=fuel_load),
24 )
25 self.m = (mdot_O, mdot_F)
26
27 def evaluate_arrays(self, P_O, P_F):
28 one = np.ones(len(P_O))
29 return {
30 "Pc": 2.7374e6 * one, "F": 6870.0 * one, "Isp": 224.5 * one, "MR": 1.506 * one,
31 "mdot_O": self.m[0] * one, "mdot_F": self.m[1] * one, "mdot_total": sum(self.m) * one,
32 "cstar_actual": 1568.0 * one, "gamma": 1.2 * one, "diagnostics": [{} for _ in P_O],
33 }
34
35
36def _run(runner, duration=3.994, n=200):
37 t = np.linspace(0.0, duration, n)
38 return ts.compute_timeseries_results(runner, t, 578.0 * np.ones(n), 578.0 * np.ones(n), run_copv=False)
39
40
42 data, summary = _run(_Runner(6.611, 7.0))
43 lox = data["lox_mass_remaining_kg"]
44 assert lox[0] == pytest.approx(6.611), "the LOX level does not start at the loaded mass"
45 assert min(lox) == 0.0, "a tank cannot hold less than nothing"
46 assert summary["lox_depletion_time_s"] == pytest.approx(6.611 / 1.8755, rel=1e-3)
47 assert summary["lox_short_kg"] == pytest.approx(1.8755 * 3.994 - 6.611, rel=1e-3)
48 assert "LOX runs dry at t = 3.5" in summary["propellant_short_note"]
49 # Fuel: 1.2451 kg/s x 3.994 s = 4.97 kg of 7.0 loaded -- 2.03 kg left, no warning for it.
50 fuel = data["fuel_mass_remaining_kg"]
51 assert fuel[0] == pytest.approx(7.0) and fuel[-1] == pytest.approx(7.0 - 1.2451 * 3.994, rel=1e-6)
52 assert "fuel_short_kg" not in summary and "Fuel" not in summary["propellant_short_note"]
53
54
56 data, summary = _run(_Runner(10.0, 10.0))
57 assert data["lox_mass_remaining_kg"][-1] == pytest.approx(10.0 - 1.8755 * 3.994, rel=1e-6)
58 assert "propellant_short_note" not in summary
59
60
62 data, summary = _run(_Runner(None, None))
63 assert data["lox_mass_remaining_kg"][0] == pytest.approx(summary["lox_propellant_kg"])
64 assert data["lox_mass_remaining_kg"][-1] == pytest.approx(0.0, abs=1e-9)
65 assert "lox_loaded_kg" not in summary and "propellant_short_note" not in summary
66
67
69 """This tab solves the curve it is given; the Flight tab truncates at dry-out."""
70 data, _ = _run(_Runner(1.0, 1.0))
71 assert all(v == pytest.approx(6.87) for v in data["thrust_kN"])
#define min(a, b)
Definition Arduino.h:42
__init__(self, lox_load, fuel_load, mdot_O=1.8755, mdot_F=1.2451)
_run(runner, duration=3.994, n=200)