24 """Volume of the solid of revolution ACTUALLY generated: cylinder, cone to the arc
25 tangency radius, then the 1.5*R_t entrance arc down to the throat.
27 This used to draw a straight cone all the way to R_t, which is not what the generator
28 makes -- so it reproduced the very convention the volume arithmetic got wrong and could
29 not catch the entrance-arc bug. See the real-contour tests at the bottom of this file.
32 x1 = np.linspace(0.0, L_cyl, n // 3)
33 r1 = np.full_like(x1, R_c)
34 x2 = np.linspace(L_cyl, L_cyl + L_con, n // 3)
35 r2 = R_c + (r_tan - R_c) * (x2 - L_cyl) / L_con
36 t = np.linspace(-(math.pi / 2 + theta), -math.pi / 2, n // 3)
37 x3 = 1.5 * R_t * np.cos(t)
38 x3 = x3 - x3[0] + (L_cyl + L_con)
39 r3 = 1.5 * R_t * np.sin(t) + 2.5 * R_t
40 x = np.concatenate([x1, x2, x3])
41 r = np.concatenate([r1, r2, r3])
42 trapz = getattr(np,
"trapezoid",
None)
or np.trapz
43 return float(trapz(math.pi * r * r, x))
46@pytest.mark.parametrize(
"D_c,Lstar", [
47 (0.127, 1.30), (0.127, 1.00), (0.127, 0.80),
48 (0.1143, 1.00), (0.1397, 1.00), (0.1524, 1.20),
50@pytest.mark.parametrize("theta", [math.radians(30.0), math.radians(45.0)])
52 A_t = 0.0018729167346808366
53 A_c = math.pi / 4 * D_c ** 2
54 R_c, R_t = D_c / 2, math.sqrt(A_t / math.pi)
57 L_cyl = chamber_length_calc(V_cmd, A_t, A_c / A_t, theta)
58 L_con = contraction_length_horizontal_calc(A_c,
_tangency_radius(R_t, theta), theta)
59 assert L_cyl > 0,
"degenerate case: no cylindrical section"
63 assert V_drawn == pytest.approx(V_cmd, rel=1e-3), (
64 f
"drawn L* = {V_drawn / A_t:.4f} but {Lstar} was commanded"
69 """The pre-fix formula overshoots by ~10 % -- proves this test has teeth."""
70 A_t = 0.0018729167346808366
72 A_c = math.pi / 4 * D_c ** 2
74 R_t = math.sqrt(A_t / math.pi)
77 old_L_cyl = (V_cmd / A_t - (1 / 3) * R_t * (1 / math.tan(theta_default))
78 * (eps ** (1 / 3) - 1)) / eps
79 L_con = contraction_length_horizontal_calc(
81 V_old =
_drawn_volume(old_L_cyl, L_con, D_c / 2, R_t, theta_default)
82 assert V_old / V_cmd > 1.05,
"old formula should overshoot volume by >5 %"
104_PC, _F, _D_EXIT = 2.965e6, 8000.0, 0.1165
108 """L* of the contour chamber_geometry_calc ACTUALLY generates, face to throat."""
109 pts, _, _ = chamber_geometry_calc(
110 pc_design=_PC, thrust_design=_F, diameter_inner=D_c,
111 diameter_exit=_D_EXIT, l_star=Lstar, steps=3000, theta=theta)
113 throat = int(np.argmin(p[:, 1]))
115 trapz = getattr(np,
"trapezoid",
None)
or np.trapz
116 vol = float(trapz(math.pi * seg[:, 1] ** 2, seg[:, 0]))
117 return vol / area_throat_calc(_PC, _F, force_coeffcient_default)
120@pytest.mark.parametrize("Lstar", [0.85, 1.00, 1.15, 1.30])
121@pytest.mark.parametrize("theta_deg", [45.0, 40.0, 35.0, 30.0])
134 """Guard the guard: if the arc term were dropped the test above must fail, not pass."""
135 A_t = area_throat_calc(_PC, _F, force_coeffcient_default)
136 R_t = math.sqrt(A_t / math.pi)
137 V_arc = entrance_arc_volume(R_t, math.radians(45.0))
139 frac = V_arc / (1.0 * A_t)
140 assert 0.005 < frac < 0.10, (
141 f
"entrance arc is {frac*100:.2f}% of a L*=1.0 chamber - outside the range that makes "
142 f
"this correction meaningful; check entrance_arc_volume()"