76 Create cache key from feed pressures.
81 Fuel feed pressure [Pa]
83 Oxidizer feed pressure [Pa]
85 Decimal places for rounding (reduces cache misses from floating point)
93 P_d_F_rounded = round(P_d_F, precision)
94 P_d_O_rounded = round(P_d_O, precision)
97 key_str = f
"{P_d_F_rounded:.{precision}f}_{P_d_O_rounded:.{precision}f}"
98 return hashlib.md5(key_str.encode()).hexdigest()
104 use_cache: bool =
True,
107 Estimate engine performance from tank/ullage pressures.
109 **IMPORTANT**: Despite the parameter names (P_d_F, P_d_O), these represent
110 TANK/ULLAGE PRESSURES (P_u_F, P_u_O), NOT feed/downstream pressures.
111 The engine physics pipeline expects tank pressures and internally calculates
117 Fuel tank/ullage pressure [Pa] (P_u_F in state vector)
118 NOTE: Parameter name is misleading - this is actually tank pressure, not feed pressure
120 Oxidizer tank/ullage pressure [Pa] (P_u_O in state vector)
121 NOTE: Parameter name is misleading - this is actually tank pressure, not feed pressure
123 Whether to use caching (default: True)
127 estimate : EngineEstimate
128 Engine performance estimate with validated thrust, MR, and mass flows
132 The engine physics pipeline (PintleEngineRunner.evaluate) expects tank pressures
133 as input. The controller state uses P_u_F and P_u_O for tank/ullage pressures,
134 which are passed directly to this function. Feed pressures (P_d_F, P_d_O) are
135 downstream and lag behind tank pressures due to line dynamics.
137 The estimate is validated to ensure consistency:
138 - If mass flows are invalid, MR is set to NaN
139 - If MR is invalid, thrust and mass flows are set to NaN
140 - If thrust is invalid, MR and mass flows are set to NaN
141 This prevents inconsistent estimates like non-zero thrust with zero MR.
146 if use_cache
and hasattr(self,
'_result_cache'):
151 if not hasattr(self,
'_result_cache'):
158 results = self.
runner.evaluate(
163 except Exception
as e:
172 injector_dp_F=np.nan,
173 injector_dp_O=np.nan,
174 stability_metrics=
None,
175 diagnostics={
"error": str(e)},
179 P_ch = results.get(
"Pc", np.nan)
182 mdot_F = results.get(
"mdot_F", np.nan)
183 mdot_O = results.get(
"mdot_O", np.nan)
186 MR = results.get(
"MR", np.nan)
189 F = results.get(
"F", np.nan)
193 if (
not np.isfinite(mdot_F)
or mdot_F <= 0)
or (
not np.isfinite(mdot_O)
or mdot_O <= 0):
194 if np.isfinite(MR)
and MR > 0:
201 if not np.isfinite(MR)
or MR <= 0:
202 if np.isfinite(F)
and F > 0:
210 if not np.isfinite(F)
or F <= 0:
211 if np.isfinite(MR)
and MR > 0:
214 if np.isfinite(mdot_F)
and mdot_F > 0:
216 if np.isfinite(mdot_O)
and mdot_O > 0:
220 if np.isfinite(MR)
and MR > 0:
221 if not np.isfinite(mdot_F)
or mdot_F <= 0:
225 if not np.isfinite(mdot_O)
or mdot_O <= 0:
231 injector_dp_F = P_d_F - P_ch
if np.isfinite(P_d_F)
and np.isfinite(P_ch)
else np.nan
232 injector_dp_O = P_d_O - P_ch
if np.isfinite(P_d_O)
and np.isfinite(P_ch)
else np.nan
235 stability_metrics =
None
236 diagnostics = results.get(
"diagnostics", {})
237 stability_results = results.get(
"stability",
None)
or results.get(
"stability_results",
None)
239 if stability_results
is not None:
241 stability_metrics = {
242 "stability_state": stability_results.get(
"stability_state",
"unknown"),
243 "stability_score": stability_results.get(
"stability_score", np.nan),
244 "chugging": stability_results.get(
"chugging", {}),
245 "acoustic": stability_results.get(
"acoustic", {}),
246 "feed_system": stability_results.get(
"feed_system", {}),
251 injector_dp_frac_F = injector_dp_F / P_d_F
if P_d_F > 0
else np.nan
252 injector_dp_frac_O = injector_dp_O / P_d_O
if P_d_O > 0
else np.nan
254 stability_metrics = {
255 "stability_state":
"unknown",
256 "stability_score": np.nan,
257 "injector_dp_frac_F": injector_dp_frac_F,
258 "injector_dp_frac_O": injector_dp_frac_O,
259 "injector_stiffness_ok": (
260 np.isfinite(injector_dp_frac_F)
and injector_dp_frac_F > 0.1
and
261 np.isfinite(injector_dp_frac_O)
and injector_dp_frac_O > 0.1
272 injector_dp_F=injector_dp_F,
273 injector_dp_O=injector_dp_O,
274 stability_metrics=stability_metrics,
275 diagnostics=diagnostics,