25 """Tail to nose tip as the sim stacks it, by hand: highest tank top + avionics length."""
27 cfg.lox_tank.ox_tank_pos + cfg.lox_tank.lox_h / 2,
28 cfg.fuel_tank.fuel_tank_pos + cfg.fuel_tank.rp1_h / 2,
29 cfg.press_tank.pres_tank_pos + cfg.press_tank.press_h / 2,
31 return max(tops) + cfg.rocket.avionics_payload_length_m
35 """0.12 base + smooth turbulent plate friction on the wetted area, Prandtl-Schlichting."""
36 from fluids.atmosphere
import ATMOSPHERE_1976
38 atm = ATMOSPHERE_1976(cfg.environment.elevation)
40 Re = mach * atm.v_sonic * L / (atm.mu / atm.rho)
41 cf = 0.455 / math.log10(Re) ** 2.58
42 fins = cfg.rocket.fins
43 s_wet = 2 * math.pi * r * L + fins.no_fins * 2 * 0.5 * (fins.root_chord + fins.tip_chord) * fins.fin_span
44 return 0.12 + cf * s_wet / (math.pi * r * r)
47@pytest.fixture(scope="module")
104 cfg.rocket.drag_curve_power_off = [[0.0, 0.6], [1.0, 0.8], [2.0, 0.7]]
105 cfg.rocket.drag_curve_power_on = [[0.0, 0.5], [1.0, 0.7], [2.0, 0.6]]
106 cfg.rocket.drag_curve_source =
"test table"
108 rocket = res[
"flight"].rocket
109 assert rocket.power_off_drag(0.5) == pytest.approx(0.7)
110 assert rocket.power_on_drag(0.5) == pytest.approx(0.6)
111 assert res[
"flight_report"][
"drag"][
"model"] ==
"table"
117 base = shipped().rocket.model_dump()
118 with pytest.raises(ValueError, match=
"go together"):
119 RocketConfig(**{**base,
"drag_curve_power_off": [[0.0, 0.5], [1.0, 0.6]]})
120 with pytest.raises(ValueError, match=
"go together"):
121 RocketConfig(**{**base,
"drag_curve_power_off": [[0.0, 0.5], [1.0, 0.6]],
"drag_curve_power_on": [[0.0, 0.5], [1.0, 0.6]]})
122 with pytest.raises(ValueError, match=
"increase"):
123 RocketConfig(**{**base,
"drag_curve_power_off": [[1.0, 0.5], [0.5, 0.6]],
"drag_curve_power_on": [[0.0, 0.5], [1.0, 0.6]],
"drag_curve_source":
"x"})
137 """(3.80): 0.032 (Rs/L)^0.2 above the critical Re, whatever Re."""
141 rough = 0.032 * (Rs / L) ** 0.2
142 assert skin_friction_cf(5e8, 0.0, Rs, L) == pytest.approx(rough, rel=1e-12)
143 assert skin_friction_cf(5e9, 0.0, Rs, L) == pytest.approx(rough, rel=1e-12)
147 fluids = pytest.importorskip(
"fluids.atmosphere")
150 for h
in (0.0, 626.67, 3000.0, 11000.0, 18000.0, 25000.0):
151 T, p, rho, a, nu = isa_troposphere(h)
152 atm = fluids.ATMOSPHERE_1976(h)
153 assert (T, p, rho, a) == pytest.approx((atm.T, atm.P, atm.rho, atm.v_sonic), rel=1e-5)
154 assert nu == pytest.approx(atm.mu / atm.rho, rel=1e-5)
169 L, R, n = 0.705, 0.078359, 200001
170 xs = [L * i / (n - 1)
for i
in range(n)]
173 th = math.acos(1 - 2 * x / L)
174 return R * math.sqrt(
max(th - math.sin(2 * th) / 2, 0.0)) / math.sqrt(math.pi)
176 ys = [y(x)
for x
in xs]
177 area = sum(math.pi * (ys[i] + ys[i + 1]) * math.hypot(xs[i + 1] - xs[i], ys[i + 1] - ys[i])
for i
in range(n - 1))
178 assert nose_wetted_area(
"vonKarman", L, R) == pytest.approx(area, rel=1e-4)