1"""Closure logic: solve branch flows with spray constraints.
3The impinging branch routes through the accelerator (engine/accel) when enabled
4(the default). The Python injector models below run for everything it doesn't
5cover — pintle, coaxial, a missing numba, or ``ED_ACCEL=off``. Dispatch is pure
6capability routing: ``accel.solve`` returns ``None`` for any config it can't
7handle and the Python model runs.
9This native fast-path matters for performance even with the Layer-1 single-call
10``ed_evaluate`` seam: ~30% of CMA candidates don't converge in the single-call native
11path and fall back to ``runner.evaluate`` → ``chamber_solver`` → here, whose Brent
12residual solves the injector many times. Keeping that native keeps the fallback fast.
14Accelerator↔Python parity is enforced by tests/test_numba_ab_parity.py, which
15diffs both live on the same inputs — there is no runtime self-check.
19from typing
import Tuple, Dict, Any, Optional
26 from engine
import accel
as _accel
37 config: PintleEngineConfig,
38) -> Optional[Tuple[float, float, Dict[str, Any]]]:
39 """Accelerated (mdot_O, mdot_F, diagnostics), or None if the accelerator is
40 disabled or can't handle this config (caller falls back to the Python model).
42 Parity is enforced by the A/B suite, not a runtime self-check (capability
43 dispatch). Strict mode (``ED_REQUIRE_ACCEL=1``, the CI
44 parity job) makes a *genuine* accelerator failure raise instead of silently
45 falling back to Python, which would report a false green. A config the kernel
46 simply doesn't handle (``solve`` returns None) still falls back quietly.
48 from engine
import accel
49 if not accel.enabled():
51 raise RuntimeError(
"strict mode set but the accelerator is not enabled/available")
53 return accel.solve(config, P_tank_O, P_tank_F, Pc)
60 config: PintleEngineConfig,
61) -> Tuple[float, float, Dict[str, Any]]:
62 """Solve injector branch flows: returns (mdot_O, mdot_F, diagnostics)."""
64 if native
is not None:
66 return get_injector_model(config).solve(P_tank_O, P_tank_F, Pc)
Tuple[float, float, Dict[str, Any]] flows(float P_tank_O, float P_tank_F, float Pc, PintleEngineConfig config)
Optional[Tuple[float, float, Dict[str, Any]]] _try_native_flows(float P_tank_O, float P_tank_F, float Pc, PintleEngineConfig config)