STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
test_compiled_hot_loops.py
Go to the documentation of this file.
1"""The compiled spray march and area-Mach bisection are the NumPy ones, not approximations of them.
2
3Both loops are compiled with numba purely for speed (together ~90 % of a Python chamber
4evaluation). Each keeps its NumPy implementation as the reference, selectable by a module flag.
5"""
6import numpy as np
7import pytest
8
9PSI = 6894.757
10
11
13 from engine.pipeline.thermal import gas_side
14 if gas_side._mach_bisect is None:
15 pytest.skip("numba unavailable")
16 rng = np.random.default_rng(3)
17 ar = np.concatenate([rng.uniform(1.0, 30.0, 200), [1.0, 1.0 + 1e-13, 4.0]])
18 for sup in (True, False):
19 for g in (1.12, 1.2, 1.4):
20 fast = gas_side.mach_from_area_ratio(ar, g, sup)
21 monkeypatch.setattr(gas_side, "_USE_COMPILED_BISECT", False)
22 ref = gas_side.mach_from_area_ratio(ar, g, sup)
23 monkeypatch.setattr(gas_side, "_USE_COMPILED_BISECT", True)
24 np.testing.assert_allclose(fast, ref, rtol=1e-14, atol=0)
25 assert isinstance(gas_side.mach_from_area_ratio(5.6, 1.14, True), float)
26
27
29 from engine.pipeline import combustion_physics as cp
30 from engine.pipeline.io import load_config
31 from engine.core.runner import PintleEngineRunner
32 if cp._march_core is None:
33 pytest.skip("numba unavailable")
34 cfg = load_config("configs/ethalox_6500N.yaml")
35 P = 584.27 * PSI
36 fast = PintleEngineRunner(cfg).evaluate(P, P, P_ambient=94070.0, silent=True)
37 monkeypatch.setattr(cp, "_USE_COMPILED_MARCH", False)
38 ref = PintleEngineRunner(cfg).evaluate(P, P, P_ambient=94070.0, silent=True)
39 for k in ("F", "Pc", "MR", "eta_cstar", "Isp"):
40 assert fast[k] == pytest.approx(ref[k], rel=1e-10), k
41 a, b = fast["diagnostics"]["cstar_efficiency"], ref["diagnostics"]["cstar_efficiency"]
42 for k in ("eta_vaporization", "frac_vaporized_F", "x_vap95_O", "x_vap95_F"):
43 # None: the stream never reached 95 % in the chamber -- both paths must
44 # agree on that too (pytest 9's approx() refuses None).
45 if b[k] is None:
46 assert a[k] is None, k
47 else:
48 assert a[k] == pytest.approx(b[k], rel=1e-10), k
49
50
52 """Coarse and fine sprays, one stream at the face, short and long chambers."""
53 from engine.pipeline import combustion_physics as cp
54 if cp._march_core is None:
55 pytest.skip("numba unavailable")
56 base = dict(Pc=2.9e6, Tc=3200.0, gamma=1.14, R=377.0, m_dot_total=2.7, Ac=0.0127,
57 u_drop0=24.0, rr_q=3.0)
58 lox = dict(name="O", mass_fraction=0.6, rho_l=1140.0, cp_l=1700.0, T0=90.0, T_s=143.0, h_fg=1.1e5)
59 eth = dict(name="F", mass_fraction=0.4, rho_l=789.0, cp_l=2440.0, T0=293.0, T_s=471.0, h_fg=5.06e5)
60 cases = []
61 for d32 in (20e-6, 60e-6, 200e-6):
62 for L in (0.05, 0.12, 0.4):
63 cases.append(([dict(lox, D32=d32), dict(eth, D32=1.3 * d32)], L))
64 cases.append(([dict(lox, D32=50e-6, instant=True), dict(eth, D32=80e-6)], 0.12))
65 for streams, L in cases:
66 fast = cp.spray_vaporization_march(streams, L_chamber=L, **base)
67 monkeypatch.setattr(cp, "_USE_COMPILED_MARCH", False)
68 ref = cp.spray_vaporization_march(streams, L_chamber=L, **base)
69 monkeypatch.setattr(cp, "_USE_COMPILED_MARCH", True)
70 assert fast["F_throat"] == pytest.approx(ref["F_throat"], rel=1e-12)
71 for name in ref["frac_vaporized"]:
72 assert fast["frac_vaporized"][name] == pytest.approx(ref["frac_vaporized"][name], rel=1e-12)
73 if ref["x_vap95"][name] is None:
74 assert fast["x_vap95"][name] is None
75 else:
76 assert fast["x_vap95"][name] == pytest.approx(ref["x_vap95"][name], rel=1e-12)
test_area_mach_bisection_matches_numpy(monkeypatch)
test_spray_march_matches_numpy_across_sprays(monkeypatch)
test_spray_march_matches_numpy_on_the_6500N(monkeypatch)