26from flight_cases
import curve_integrals, fly, fly_helpers, header_curve, roomy_tanks, shipped
44 for name, sec, rho_l
in ((
"LOX Tank", cfg.lox_tank, 1140.0), (
"Fuel Tank", cfg.fuel_tank, 789.0)):
45 V = sec.tank_volume_m3
46 V_ull = V - sec.mass / rho_l
47 rho_g = CP.PropsSI(
"D",
"P", sec.initial_pressure_psi * PSI,
"T", 293.15,
"Nitrogen")
48 tank =
_tank(res, name)
49 assert tank.gas_volume(0) == pytest.approx(0.999 * V_ull, abs=1e-9)
50 assert tank.gas_mass(0) == pytest.approx(0.999 * V_ull * rho_g, rel=1e-6)
52 assert cfg.lox_tank.tank_volume_m3 - cfg.lox_tank.mass / 1140.0 == pytest.approx(0.6444e-3, abs=1e-6)
53 assert cfg.fuel_tank.tank_volume_m3 - cfg.fuel_tank.mass / 789.0 == pytest.approx(0.6202e-3, abs=1e-6)
57 """A 5 L LOX tank at 90 % fill: 0.5 L of ullage, half what the old seed demanded."""
58 cfg = roomy_tanks(shipped())
60 cfg.lox_tank.tank_volume_m3 = V
61 cfg.lox_tank.lox_h = V / (math.pi * cfg.lox_tank.lox_radius**2)
62 cfg.lox_tank.mass = 0.9 * V * 1140.0
64 assert _tank(res,
"LOX Tank").gas_volume(0) == pytest.approx(0.999 * 0.1 * V, abs=1e-9)
65 assert res[
"truncation_info"][
"reason"] ==
"LOX"
81 """Loads at the curve's own integral burn the whole curve, whichever side of it they fall."""
82 I, IO, IF = curve_integrals()
83 cfg = roomy_tanks(shipped())
84 cfg.lox_tank.mass, cfg.fuel_tank.mass = IO * scale, IF * scale
86 motor = res[
"flight"].rocket.motor
87 assert motor.total_impulse / I - 1 == pytest.approx(0.0, abs=5e-4)
88 if res[
"truncation_info"][
"truncated"]:
89 assert res[
"truncation_info"][
"cutoff_time"] == pytest.approx(motor.burn_out_time, abs=1e-3)
93 """Was 3941 / 3890 / 4033 m for x(1, 1+1e-9, 1+1e-6). RocketPy's own integrator scatter on
94 this vehicle is under 1 m, so that is the bound."""
95 _, IO, IF = curve_integrals()
97 for scale
in (1 - 1e-9, 1.0, 1 + 1e-9, 1 + 1e-6):
98 cfg = roomy_tanks(shipped())
99 cfg.lox_tank.mass, cfg.fuel_tank.mass = IO * scale, IF * scale
100 apogees.append(
fly(cfg)[
"apogee"])
101 assert max(apogees) -
min(apogees) < 1.0, apogees
105 I, IO, IF = curve_integrals()
106 cfg = roomy_tanks(shipped())
107 cfg.lox_tank.mass, cfg.fuel_tank.mass = IO * 0.99, IF * 0.99
109 motor = res[
"flight"].rocket.motor
110 assert motor.total_impulse / I - 1 == pytest.approx(-0.0100, abs=5e-4)
111 assert res[
"truncation_info"][
"cutoff_time"] == pytest.approx(motor.burn_out_time, abs=1e-3)
115 """Vehicle mass falls by exactly the propellant burned: the refill is a transfer."""
116 t, F, mO, mF = header_curve()
118 rocket = res[
"flight"].rocket
119 tb = rocket.motor.burn_out_time
121 burned = float(np.interp(tb, t, np.concatenate([[0.0], np.cumsum(0.5 * (md[1:] + md[:-1]) * np.diff(t))])))
122 assert rocket.total_mass(0.0) - rocket.total_mass(tb + 5.0) == pytest.approx(burned, abs=1e-4)
123 copv =
_tank(res,
"Pressurant (Nā) Tank")
124 refill = copv.fluid_mass(0.0) - copv.fluid_mass(tb)
125 assert refill > 0.4,
"the COPV should have refilled ~0.5 kg of ullage"
126 assert res[
"flight_report"][
"copv_refill_kg"] == pytest.approx(refill, rel=2e-3)