STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
run_ablative_graphite_pipeline.py
Go to the documentation of this file.
1"""Run full pipeline with ablative and graphite modeling to see thrust performance."""
2
3from pathlib import Path
4import sys
5import numpy as np
6import matplotlib.pyplot as plt
7
8sys.path.insert(0, str(Path(__file__).parent.parent))
9
10from engine.pipeline.io import load_config
11from engine.core.runner import PintleEngineRunner
12
13# Load configuration
14config_path = Path(__file__).parent.parent / "configs" / "default.yaml"
15config = load_config(str(config_path))
16
17# Enable ablative cooling and geometry tracking
18config.ablative_cooling.enabled = True
19config.ablative_cooling.track_geometry_evolution = True
20
21# Enable graphite insert if configured
22if hasattr(config, 'graphite_insert'):
23 config.graphite_insert.enabled = True
24 print("Graphite insert: ENABLED")
25else:
26 print("Graphite insert: Not configured (check config file)")
27
28print("=" * 80)
29print("FULL PIPELINE: ABLATIVE + GRAPHITE MODELING")
30print("=" * 80)
31
32# Create runner
33runner = PintleEngineRunner(config)
34
35# Define time series (10 second burn)
36burn_time = 10.0 # seconds
37n_points = 100
38times = np.linspace(0, burn_time, n_points)
39
40# Constant tank pressures
41P_tank_O_psi = 1305.0
42P_tank_F_psi = 974.0
43P_tank_O = np.full(n_points, P_tank_O_psi * 6894.76)
44P_tank_F = np.full(n_points, P_tank_F_psi * 6894.76)
45
46print(f"\nTest Conditions:")
47print(f" Burn time: {burn_time:.1f} s")
48print(f" Time points: {n_points}")
49print(f" LOX tank pressure: {P_tank_O_psi:.0f} psi (constant)")
50print(f" Fuel tank pressure: {P_tank_F_psi:.0f} psi (constant)")
51
52print(f"\nAblative Configuration:")
53print(f" Enabled: {config.ablative_cooling.enabled}")
54print(f" Track geometry: {config.ablative_cooling.track_geometry_evolution}")
55print(f" Material: {config.ablative_cooling.material_density:.0f} kg/m³")
56print(f" Heat of ablation: {config.ablative_cooling.heat_of_ablation/1e6:.1f} MJ/kg")
57
58if hasattr(config, 'graphite_insert') and config.graphite_insert.enabled:
59 print(f"\nGraphite Insert Configuration:")
60 print(f" Enabled: {config.graphite_insert.enabled}")
61 print(f" Coverage: {config.graphite_insert.coverage_fraction*100:.0f}%")
62 if hasattr(config.graphite_insert, 'initial_thickness'):
63 print(f" Initial Thickness: {config.graphite_insert.initial_thickness*1000:.2f} mm")
64
65print(f"\n{'='*80}")
66print("RUNNING TIME-SERIES SIMULATION WITH GEOMETRY EVOLUTION...")
67print("=" * 80)
68
69# Run time-varying simulation
70results = runner.evaluate_arrays_with_time(times, P_tank_O, P_tank_F)
71
72print(f"\n✅ Simulation complete!")
73
74# Extract results
75thrust_kN = results["F"] / 1000.0
76Isp = results["Isp"]
77Pc_psi = results["Pc"] / 6894.76
78Lstar = results["Lstar"]
79A_throat = results["A_throat"]
80V_chamber = results["V_chamber"]
81recession_chamber = results.get("recession_chamber", np.zeros_like(times))
82recession_throat = results.get("recession_throat", np.zeros_like(times))
83
84# Calculate performance metrics
85thrust_loss_pct = (1.0 - results["F"][-1] / results["F"][0]) * 100
86Lstar_change_pct = (results["Lstar"][-1] / results["Lstar"][0] - 1.0) * 100
87throat_area_change_pct = (results["A_throat"][-1] / results["A_throat"][0] - 1.0) * 100
88
89print(f"\n{'='*80}")
90print("THRUST PERFORMANCE SUMMARY")
91print("=" * 80)
92print(f"Initial Thrust: {thrust_kN[0]:.2f} kN")
93print(f"Final Thrust: {thrust_kN[-1]:.2f} kN")
94print(f"Thrust Loss: {thrust_loss_pct:.2f}%")
95print(f"\nInitial Isp: {Isp[0]:.1f} s")
96print(f"Final Isp: {Isp[-1]:.1f} s")
97print(f"Isp Loss: {(1.0 - Isp[-1]/Isp[0])*100:.2f}%")
98print(f"\nInitial Chamber P: {Pc_psi[0]:.1f} psi")
99print(f"Final Chamber P: {Pc_psi[-1]:.1f} psi")
100print(f"Chamber P Change: {(Pc_psi[-1]/Pc_psi[0] - 1.0)*100:.2f}%")
101print(f"\nInitial L*: {Lstar[0]*1000:.1f} mm")
102print(f"Final L*: {Lstar[-1]*1000:.1f} mm")
103print(f"L* Change: {Lstar_change_pct:.2f}%")
104print(f"\nInitial Throat Area: {A_throat[0]*1e6:.2f} mm²")
105print(f"Final Throat Area: {A_throat[-1]*1e6:.2f} mm²")
106print(f"Throat Area Change: {throat_area_change_pct:.2f}%")
107print(f"\nMax Chamber Recession: {np.max(recession_chamber)*1e6:.2f} µm")
108print(f"Max Throat Recession: {np.max(recession_throat)*1e6:.2f} µm")
109
110# Create plots
111fig, axes = plt.subplots(2, 3, figsize=(18, 12))
112fig.suptitle('Ablative + Graphite Pipeline: Thrust Performance', fontsize=16, fontweight='bold')
113
114# Plot 1: Thrust over time
115ax = axes[0, 0]
116ax.plot(times, thrust_kN, 'b-', linewidth=2, label='Thrust')
117ax.set_xlabel('Time (s)')
118ax.set_ylabel('Thrust (kN)')
119ax.set_title('Thrust vs Time')
120ax.grid(True, alpha=0.3)
121ax.legend()
122
123# Plot 2: Isp over time
124ax = axes[0, 1]
125ax.plot(times, Isp, 'g-', linewidth=2, label='Isp')
126ax.set_xlabel('Time (s)')
127ax.set_ylabel('Specific Impulse (s)')
128ax.set_title('Isp vs Time')
129ax.grid(True, alpha=0.3)
130ax.legend()
131
132# Plot 3: Chamber Pressure
133ax = axes[0, 2]
134ax.plot(times, Pc_psi, 'r-', linewidth=2, label='Chamber Pressure')
135ax.set_xlabel('Time (s)')
136ax.set_ylabel('Chamber Pressure (psi)')
137ax.set_title('Chamber Pressure vs Time')
138ax.grid(True, alpha=0.3)
139ax.legend()
140
141# Plot 4: L* Evolution
142ax = axes[1, 0]
143ax.plot(times, Lstar * 1000, 'm-', linewidth=2, label='L*')
144ax.set_xlabel('Time (s)')
145ax.set_ylabel('L* (mm)')
146ax.set_title('Characteristic Length Evolution')
147ax.grid(True, alpha=0.3)
148ax.legend()
149
150# Plot 5: Throat Area Evolution
151ax = axes[1, 1]
152ax.plot(times, A_throat * 1e6, 'orange', linewidth=2, label='Throat Area')
153ax.set_xlabel('Time (s)')
154ax.set_ylabel('Throat Area (mm²)')
155ax.set_title('Throat Area Evolution')
156ax.grid(True, alpha=0.3)
157ax.legend()
158
159# Plot 6: Recession
160ax = axes[1, 2]
161ax.plot(times, recession_chamber * 1e6, 'purple', linewidth=2, label='Chamber Recession')
162ax.plot(times, recession_throat * 1e6, 'orange', linewidth=2, label='Throat Recession')
163ax.set_xlabel('Time (s)')
164ax.set_ylabel('Recession (µm)')
165ax.set_title('Cumulative Recession')
166ax.grid(True, alpha=0.3)
167ax.legend()
168
169plt.tight_layout()
170
171# Save plot
172output_path = Path(__file__).parent / "ablative_graphite_thrust_performance.png"
173plt.savefig(output_path, dpi=150, bbox_inches='tight')
174print(f"\n✅ Plot saved to: {output_path}")
175
176# Show plot
177plt.show()
178
179print(f"\n{'='*80}")
180print("SIMULATION COMPLETE")
181print("=" * 80)
182