1"""Comprehensive system diagnostics for validating all dynamics and identifying issues."""
4from typing
import Dict, Any, Optional, List
10 """Comprehensive diagnostics for engine system dynamics."""
12 def __init__(self, config: PintleEngineConfig):
16 def diagnose_all(self, P_tank_O: float, P_tank_F: float) -> Dict[str, Any]:
18 Run comprehensive diagnostics on all system components.
23 Comprehensive diagnostic results with issues and recommendations
29 engine_results = self.
runner.evaluate(P_tank_O, P_tank_F)
30 results[
"engine_evaluation"] = engine_results
31 except Exception
as e:
32 results[
"engine_evaluation"] = {
"error": str(e)}
36 Pc = engine_results.get(
"Pc", 0.0)
37 MR = engine_results.get(
"MR", 0.0)
38 mdot_total = engine_results.get(
"mdot_total", 0.0)
39 F = engine_results.get(
"F", 0.0)
40 Isp = engine_results.get(
"Isp", 0.0)
41 Cf_actual = engine_results.get(
"Cf_actual", 0.0)
42 Cf_ideal = engine_results.get(
"Cf_ideal", 0.0)
43 Cf_theoretical = engine_results.get(
"Cf_theoretical", 0.0)
44 v_exit = engine_results.get(
"v_exit", 0.0)
45 T_exit = engine_results.get(
"T_exit", 0.0)
46 P_exit = engine_results.get(
"P_exit", 0.0)
47 M_exit = engine_results.get(
"M_exit", 0.0)
51 cg = ensure_chamber_geometry(self.
config)
52 results[
"cf_analysis"] = self.
_diagnose_cf(Cf_actual, Cf_ideal, Cf_theoretical, F, Pc, cg.A_throat)
53 results[
"velocity_analysis"] = self.
_diagnose_velocity(v_exit, T_exit, P_exit, M_exit, engine_results)
63 def _diagnose_cf(self, Cf_actual: float, Cf_ideal: float, Cf_theoretical: float,
64 F: float, Pc: float, A_throat: float) -> Dict[str, Any]:
65 """Diagnose thrust coefficient calculations."""
71 issues.append(
"Cf_actual is zero or negative - thrust calculation may be wrong")
73 issues.append(f
"Cf_actual ({Cf_actual:.4f}) is unusually low (< 1.0)")
74 recommendations.append(
"Check exit velocity and pressure calculations")
76 issues.append(f
"Cf_actual ({Cf_actual:.4f}) is unusually high (> 2.5)")
77 recommendations.append(
"Check for calculation errors or underexpanded nozzle")
80 if Cf_actual > Cf_ideal * 1.2:
81 issues.append(f
"Cf_actual ({Cf_actual:.4f}) > Cf_ideal ({Cf_ideal:.4f}) by >20%")
82 recommendations.append(
"May indicate underexpanded nozzle or calculation error")
84 if abs(Cf_actual - Cf_theoretical) /
max(Cf_theoretical, 0.01) > 0.1:
85 issues.append(f
"Cf_actual ({Cf_actual:.4f}) differs significantly from Cf_theoretical ({Cf_theoretical:.4f})")
86 recommendations.append(
"Check momentum and pressure thrust components")
89 F_calculated = Cf_actual * Pc * A_throat
90 if abs(F - F_calculated) /
max(F, 1.0) > 0.01:
91 issues.append(f
"Thrust equation mismatch: F={F:.1f} N vs Cf*Pc*At={F_calculated:.1f} N")
92 recommendations.append(
"Verify Cf_actual calculation")
95 "Cf_actual": Cf_actual,
97 "Cf_theoretical": Cf_theoretical,
99 "F_expected": F_calculated,
101 "recommendations": recommendations,
102 "status":
"OK" if len(issues) == 0
else "ISSUES"
106 M_exit: float, engine_results: Dict) -> Dict[str, Any]:
107 """Diagnose velocity and Mach number calculations."""
113 issues.append(
"Exit velocity is zero or negative")
115 issues.append(f
"Exit velocity ({v_exit:.1f} m/s) is unusually low")
116 recommendations.append(
"Check exit temperature and Mach number calculations")
118 issues.append(f
"Exit velocity ({v_exit:.1f} m/s) is unusually high")
119 recommendations.append(
"Verify exit temperature and Mach number")
123 issues.append(
"Exit Mach number is zero or negative")
125 issues.append(f
"Exit Mach number ({M_exit:.3f}) is subsonic - should be > 1.0 for supersonic nozzle")
126 recommendations.append(
"Check area-Mach number solver convergence")
128 issues.append(f
"Exit Mach number ({M_exit:.2f}) is unusually high (> 10)")
129 recommendations.append(
"Verify expansion ratio and area-Mach solver")
132 Tc = engine_results.get(
"Tc", 0.0)
134 issues.append(
"Exit temperature is zero or negative")
135 elif T_exit > Tc * 0.95:
136 issues.append(f
"Exit temperature ({T_exit:.1f} K) is too close to chamber temperature ({Tc:.1f} K)")
137 recommendations.append(
"Check isentropic expansion calculation")
138 elif T_exit < Tc * 0.2:
139 issues.append(f
"Exit temperature ({T_exit:.1f} K) is unusually low compared to chamber ({Tc:.1f} K)")
140 recommendations.append(
"Verify Mach number and isentropic relations")
143 chamber_intrinsics = engine_results.get(
"chamber_intrinsics", {})
144 M_chamber = chamber_intrinsics.get(
"mach_number", 0.0)
146 issues.append(
"Chamber Mach number is zero or negative")
147 elif M_chamber > 0.5:
148 issues.append(f
"Chamber Mach number ({M_chamber:.3f}) is unusually high (> 0.5)")
149 recommendations.append(
"Check mean velocity calculation in chamber")
152 gamma = engine_results.get(
"gamma", 1.2)
153 R = engine_results.get(
"R", 300.0)
154 sound_speed = np.sqrt(gamma * R * T_exit)
155 v_expected = M_exit * sound_speed
156 if abs(v_exit - v_expected) /
max(v_exit, 1.0) > 0.01:
157 issues.append(f
"Velocity-Mach mismatch: v_exit={v_exit:.1f} m/s vs M*a={v_expected:.1f} m/s")
158 recommendations.append(
"Verify exit velocity calculation consistency")
165 "M_chamber": M_chamber,
167 "recommendations": recommendations,
168 "status":
"OK" if len(issues) == 0
else "ISSUES"
172 engine_results: Dict) -> Dict[str, Any]:
173 """Diagnose feed system pressure losses."""
177 diagnostics = engine_results.get(
"diagnostics", {})
178 delta_p_feed_O = diagnostics.get(
"delta_p_feed_O", 0.0)
179 delta_p_feed_F = diagnostics.get(
"delta_p_feed_F", 0.0)
180 mdot_O = diagnostics.get(
"mdot_O", 0.0)
181 mdot_F = diagnostics.get(
"mdot_F", 0.0)
184 if delta_p_feed_O == 0.0
and mdot_O > 0.01:
185 issues.append(f
"LOX feed pressure loss is zero with mdot_O={mdot_O:.4f} kg/s")
186 recommendations.append(
"Check feed system configuration (d_inlet, A_hydraulic, K_eff)")
187 recommendations.append(
"Verify delta_p_feed function is being called correctly")
188 elif delta_p_feed_O < 0:
189 issues.append(f
"LOX feed pressure loss is negative: {delta_p_feed_O:.1f} Pa")
190 elif delta_p_feed_O > P_tank_O * 0.5:
191 issues.append(f
"LOX feed pressure loss ({delta_p_feed_O/1e6:.2f} MPa) is >50% of tank pressure")
192 recommendations.append(
"Check feed system geometry - may be too restrictive")
195 if delta_p_feed_F == 0.0
and mdot_F > 0.01:
196 issues.append(f
"Fuel feed pressure loss is zero with mdot_F={mdot_F:.4f} kg/s")
197 recommendations.append(
"Check feed system configuration")
198 elif delta_p_feed_F < 0:
199 issues.append(f
"Fuel feed pressure loss is negative: {delta_p_feed_F:.1f} Pa")
200 elif delta_p_feed_F > P_tank_F * 0.5:
201 issues.append(f
"Fuel feed pressure loss ({delta_p_feed_F/1e6:.2f} MPa) is >50% of tank pressure")
202 recommendations.append(
"Check feed system geometry")
205 P_injector_O = diagnostics.get(
"P_injector_O", 0.0)
206 P_injector_F = diagnostics.get(
"P_injector_F", 0.0)
207 Pc = engine_results.get(
"Pc", 0.0)
209 if P_injector_O <= Pc:
210 issues.append(f
"LOX injector pressure ({P_injector_O/1e6:.2f} MPa) <= chamber pressure ({Pc/1e6:.2f} MPa)")
211 recommendations.append(
"Increase tank pressure or reduce feed losses")
213 if P_injector_F <= Pc:
214 issues.append(f
"Fuel injector pressure ({P_injector_F/1e6:.2f} MPa) <= chamber pressure ({Pc/1e6:.2f} MPa)")
215 recommendations.append(
"Increase tank pressure or reduce feed losses")
218 "delta_p_feed_O": delta_p_feed_O,
219 "delta_p_feed_F": delta_p_feed_F,
220 "P_injector_O": P_injector_O,
221 "P_injector_F": P_injector_F,
222 "P_tank_O": P_tank_O,
223 "P_tank_F": P_tank_F,
227 "recommendations": recommendations,
228 "status":
"OK" if len(issues) == 0
else "ISSUES"
232 """Diagnose chamber dynamics (L*, residence time, velocities)."""
236 chamber_intrinsics = engine_results.get(
"chamber_intrinsics", {})
237 Lstar = chamber_intrinsics.get(
"Lstar", 0.0)
238 residence_time = chamber_intrinsics.get(
"residence_time", 0.0)
239 velocity_mean = chamber_intrinsics.get(
"velocity_mean", 0.0)
240 velocity_throat = chamber_intrinsics.get(
"velocity_throat", 0.0)
241 mach_number = chamber_intrinsics.get(
"mach_number", 0.0)
245 issues.append(
"L* is zero or negative")
247 issues.append(f
"L* ({Lstar:.3f} m) is unusually short (< 0.5 m)")
248 recommendations.append(
"May cause incomplete combustion - check chamber volume")
250 issues.append(f
"L* ({Lstar:.3f} m) is unusually long (> 3.0 m)")
251 recommendations.append(
"May cause excessive weight - optimize chamber geometry")
254 if residence_time <= 0:
255 issues.append(
"Residence time is zero or negative")
256 elif residence_time < 1e-4:
257 issues.append(f
"Residence time ({residence_time*1e3:.3f} ms) is unusually short")
258 recommendations.append(
"May cause incomplete combustion")
259 elif residence_time > 0.1:
260 issues.append(f
"Residence time ({residence_time*1e3:.1f} ms) is unusually long")
261 recommendations.append(
"Check mass flow and chamber volume")
264 if velocity_mean <= 0:
265 issues.append(
"Mean chamber velocity is zero or negative")
266 elif velocity_mean > 500:
267 issues.append(f
"Mean chamber velocity ({velocity_mean:.1f} m/s) is unusually high")
268 recommendations.append(
"Check mean velocity calculation")
270 if velocity_throat <= 0:
271 issues.append(
"Throat velocity is zero or negative")
272 elif abs(velocity_throat - velocity_mean * 10) < velocity_mean:
273 issues.append(f
"Throat velocity ({velocity_throat:.1f} m/s) seems inconsistent with mean ({velocity_mean:.1f} m/s)")
277 "residence_time": residence_time,
278 "velocity_mean": velocity_mean,
279 "velocity_throat": velocity_throat,
280 "mach_number": mach_number,
282 "recommendations": recommendations,
283 "status":
"OK" if len(issues) == 0
else "ISSUES"
287 """Diagnose stability analysis results."""
291 stability = engine_results.get(
"stability_results", {})
292 is_stable = stability.get(
"is_stable",
True)
295 issues.append(
"Engine is predicted to be unstable")
296 recommendations.append(
"Review stability analysis results")
298 chugging = stability.get(
"chugging", {})
299 chugging_freq = chugging.get(
"frequency", 0.0)
300 if chugging_freq <= 0:
301 issues.append(
"Chugging frequency is zero or negative")
302 elif chugging_freq < 1.0:
303 issues.append(f
"Chugging frequency ({chugging_freq:.2f} Hz) is unusually low")
306 "is_stable": is_stable,
307 "chugging_frequency": chugging_freq,
309 "recommendations": recommendations,
310 "status":
"OK" if is_stable
and len(issues) == 0
else "ISSUES"
314 """Overall system health assessment."""
316 all_recommendations = []
318 for component, data
in results.items():
319 if isinstance(data, dict)
and "issues" in data:
320 all_issues.extend([f
"{component}: {issue}" for issue
in data[
"issues"]])
321 all_recommendations.extend([f
"{component}: {rec}" for rec
in data.get(
"recommendations", [])])
323 status =
"HEALTHY" if len(all_issues) == 0
else "NEEDS_ATTENTION"
324 if len(all_issues) > 5:
329 "total_issues": len(all_issues),
330 "issues": all_issues,
331 "recommendations": all_recommendations
__init__(self, PintleEngineConfig config)
Dict[str, Any] _diagnose_cf(self, float Cf_actual, float Cf_ideal, float Cf_theoretical, float F, float Pc, float A_throat)
Dict[str, Any] _diagnose_feed_system(self, float P_tank_O, float P_tank_F, Dict engine_results)
Dict[str, Any] _diagnose_stability(self, Dict engine_results)
Dict[str, Any] _diagnose_velocity(self, float v_exit, float T_exit, float P_exit, float M_exit, Dict engine_results)
Dict[str, Any] diagnose_all(self, float P_tank_O, float P_tank_F)
Dict[str, Any] _diagnose_chamber_dynamics(self, Dict engine_results)
Dict[str, Any] _overall_health(self, Dict results)