STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
localized_ablation.py
Go to the documentation of this file.
1"""Localized ablation modeling at fuel impingement points.
2
3This module models enhanced ablation at locations where fuel spray impinges
4on the ablative liner, accounting for:
51. Direct impingement heat flux
62. Enhanced local heat transfer
73. Spatial distribution of impingement zones
84. Time-varying impingement patterns
9"""
10
11from __future__ import annotations
12
13from typing import Dict, Tuple, Optional, List
14import numpy as np
15from engine.pipeline.config_schemas import PintleEngineConfig, PintleInjectorConfig
16
17
19 config: PintleEngineConfig,
20 chamber_length: float,
21 chamber_diameter: float,
22 n_points: int = 100,
23) -> Dict[str, np.ndarray]:
24 """
25 Calculate spatial distribution of fuel impingement zones on chamber wall.
26
27 For pintle injectors, fuel sprays radially outward and impinges on the
28 chamber wall at specific axial and circumferential locations.
29
30 Parameters:
31 -----------
32 config : PintleEngineConfig
33 Engine configuration
34 chamber_length : float
35 Chamber length [m]
36 chamber_diameter : float
37 Chamber diameter [m]
38 n_points : int
39 Number of axial points to evaluate
40
41 Returns:
42 --------
43 impingement_data : dict
44 - axial_positions: Array of axial positions [m]
45 - impingement_heat_flux_multiplier: Local heat flux multiplier (1.0 = baseline, >1.0 = enhanced)
46 - impingement_zones: Boolean array indicating impingement zones
47 - spray_angle: Spray angle at each position [rad]
48 - impingement_distance: Distance from injector to wall [m]
49 """
50 if not hasattr(config, 'injector') or config.injector.type != "pintle":
51 # No impingement for non-pintle injectors
52 positions = np.linspace(0, chamber_length, n_points)
53 return {
54 "axial_positions": positions,
55 "impingement_heat_flux_multiplier": np.ones_like(positions),
56 "impingement_zones": np.zeros_like(positions, dtype=bool),
57 "spray_angle": np.zeros_like(positions),
58 "impingement_distance": np.full_like(positions, np.nan),
59 }
60
61 injector_config: PintleInjectorConfig = config.injector
62 geometry = injector_config.geometry
63
64 # Get pintle geometry
65 d_pintle_tip = geometry.fuel.d_pintle_tip
66 theta_orifice = geometry.lox.theta_orifice # Orifice angle [deg]
67 n_orifices = geometry.lox.n_orifices
68
69 # Calculate spray characteristics
70 # Fuel sprays radially from pintle tip
71 # LOX sprays axially at angle theta_orifice
72 # Combined spray impinges on wall
73
74 positions = np.linspace(0, chamber_length, n_points)
75
76 # Calculate where fuel spray impinges on wall
77 # Assuming radial fuel spray and axial LOX spray
78 # Impingement occurs where spray trajectory intersects chamber wall
79
80 # Simplified model: impingement occurs at distance from injector
81 # based on spray angle and chamber radius
82 R_chamber = chamber_diameter / 2.0
83 R_pintle = d_pintle_tip / 2.0
84
85 # Fuel spray angle (radial, ~90 degrees from axis)
86 # Combined spray angle depends on momentum flux ratio
87 # For now, use simplified model based on orifice angle
88 spray_angle_deg = theta_orifice # Approximate
89 spray_angle = np.deg2rad(spray_angle_deg)
90
91 # Distance from injector to wall impingement
92 # For radial spray: L_impinge ≈ R_chamber / tan(spray_angle)
93 # For small angles, L_impinge ≈ R_chamber / spray_angle
94 if spray_angle > 0.01:
95 L_impinge = R_chamber / np.tan(spray_angle)
96 else:
97 L_impinge = chamber_length * 0.1 # Default: 10% of chamber length
98
99 # Impingement zone: region where spray hits wall
100 # Use Gaussian distribution around impingement point
101 impingement_center = min(L_impinge, chamber_length * 0.3) # Typically in first 30% of chamber
102 impingement_width = chamber_length * 0.1 # 10% of chamber length
103
104 # Calculate impingement intensity (Gaussian distribution)
105 impingement_intensity = np.exp(-0.5 * ((positions - impingement_center) / (impingement_width / 3)) ** 2)
106
107 # Heat flux multiplier: enhanced ablation at impingement zones
108 # Typical enhancement: 2-5x baseline heat flux
109 base_multiplier = 1.0
110 max_multiplier = 3.5 # 3.5x enhancement at peak impingement
111 heat_flux_multiplier = base_multiplier + (max_multiplier - base_multiplier) * impingement_intensity
112
113 # Identify impingement zones (where multiplier > 1.5)
114 impingement_zones = heat_flux_multiplier > 1.5
115
116 # Calculate spray angle at each position
117 # Spray angle decreases with distance from injector
118 spray_angles = np.full_like(positions, spray_angle)
119 # At impingement, spray angle is perpendicular to wall
120 near_impingement = np.abs(positions - impingement_center) < impingement_width
121 spray_angles[near_impingement] = np.pi / 2.0 # Perpendicular
122
123 # Impingement distance (distance from injector to wall at each position)
124 impingement_distances = np.sqrt((positions - 0) ** 2 + R_chamber ** 2)
125
126 return {
127 "axial_positions": positions,
128 "impingement_heat_flux_multiplier": heat_flux_multiplier,
129 "impingement_zones": impingement_zones,
130 "spray_angle": spray_angles,
131 "impingement_distance": impingement_distances,
132 "impingement_center": impingement_center,
133 "impingement_width": impingement_width,
134 }
135
136
138 base_heat_flux: np.ndarray,
139 impingement_data: Dict[str, np.ndarray],
140 base_recession_rate: np.ndarray,
141 ablative_config,
142) -> np.ndarray:
143 """
144 Calculate localized recession rates accounting for fuel impingement.
145
146 Parameters:
147 -----------
148 base_heat_flux : np.ndarray
149 Baseline heat flux [W/m²] at each axial position
150 impingement_data : dict
151 Output from calculate_impingement_zones()
152 base_recession_rate : np.ndarray
153 Baseline recession rate [m/s] (without impingement enhancement)
154 ablative_config : AblativeCoolingConfig
155 Ablative configuration
156
157 Returns:
158 --------
159 localized_recession_rate : np.ndarray
160 Enhanced recession rate [m/s] accounting for impingement
161 """
162 multiplier = impingement_data["impingement_heat_flux_multiplier"]
163
164 # Enhanced heat flux at impingement zones
165 enhanced_heat_flux = base_heat_flux * multiplier
166
167 # Enhanced recession rate (proportional to heat flux)
168 # Recession rate scales with heat flux: ṙ ∝ q / (H_ablation × ρ)
169 localized_recession_rate = base_recession_rate * multiplier
170
171 return localized_recession_rate
172
173
175 config: PintleEngineConfig,
176 axial_position: float,
177 chamber_length: float,
178) -> float:
179 """
180 Get heat flux enhancement factor at a specific axial position.
181
182 Parameters:
183 -----------
184 config : PintleEngineConfig
185 Engine configuration
186 axial_position : float
187 Axial position along chamber [m]
188 chamber_length : float
189 Chamber length [m]
190
191 Returns:
192 --------
193 enhancement_factor : float
194 Heat flux multiplier (1.0 = baseline, >1.0 = enhanced)
195 """
196 impingement_data = calculate_impingement_zones(config, chamber_length, 0.1, n_points=100)
197 positions = impingement_data["axial_positions"]
198 multipliers = impingement_data["impingement_heat_flux_multiplier"]
199
200 # Interpolate to get multiplier at specific position
201 if axial_position <= positions[0]:
202 return multipliers[0]
203 elif axial_position >= positions[-1]:
204 return multipliers[-1]
205 else:
206 return np.interp(axial_position, positions, multipliers)
207
#define min(a, b)
Definition Arduino.h:42
Dict[str, np.ndarray] calculate_impingement_zones(PintleEngineConfig config, float chamber_length, float chamber_diameter, int n_points=100)
float get_impingement_enhancement_factor(PintleEngineConfig config, float axial_position, float chamber_length)
np.ndarray calculate_localized_recession(np.ndarray base_heat_flux, Dict[str, np.ndarray] impingement_data, np.ndarray base_recession_rate, ablative_config)