21 L_nozzle: float = 0.0,
22 expansion_ratio: float = 10.0,
23 ablative_config: Optional[AblativeCoolingConfig] =
None,
24 graphite_config: Optional[GraphiteInsertConfig] =
None,
25 recession_chamber: float = 0.0,
26 recession_graphite: float = 0.0,
28) -> Dict[str, np.ndarray]:
30 Calculate chamber geometry with FIXED constant outer diameter.
33 - Gas boundary (inner surface)
34 - Ablative liner (chamber region only)
35 - Graphite insert (throat region only)
36 - Stainless steel (CONSTANT outer diameter)
43 Chamber inner diameter [m] (after recession)
48 expansion_ratio : float
49 Nozzle expansion ratio
50 ablative_config : AblativeCoolingConfig, optional
51 Ablative configuration
52 graphite_config : GraphiteInsertConfig, optional
53 Graphite configuration
54 recession_chamber : float
56 recession_graphite : float
57 Graphite recession [m]
59 Number of points for geometry
64 - positions: Axial positions [m]
65 - R_gas: Gas boundary radius [m]
66 - R_ablative_outer: Ablative outer radius [m]
67 - R_graphite_outer: Graphite outer radius [m]
68 - R_stainless: Stainless outer radius [m] (CONSTANT)
69 - throat_position: Throat axial position [m]
70 - graphite_start: Graphite start position [m]
71 - graphite_end: Graphite end position [m]
74 L_total = L_chamber + L_nozzle
77 positions = np.linspace(0.0, L_total, n_points)
80 throat_pos = L_chamber
83 A_throat = np.pi * (D_throat / 2.0) ** 2
84 A_exit = A_throat * expansion_ratio
85 D_exit = np.sqrt(4.0 * A_exit / np.pi)
88 R_gas = np.zeros(n_points)
89 for i, x
in enumerate(positions):
92 R_gas[i] = D_chamber / 2.0
93 elif x < throat_pos + L_nozzle:
95 x_nozzle = (x - throat_pos) / L_nozzle
if L_nozzle > 0
else 0.0
96 R_throat = D_throat / 2.0
99 R_gas[i] = R_throat + (R_exit - R_throat) * x_nozzle
102 R_gas[i] = D_exit / 2.0
105 if ablative_config
and ablative_config.enabled:
106 ablative_thickness =
max(
107 ablative_config.initial_thickness - recession_chamber,
110 R_ablative_outer = np.zeros_like(positions)
111 for i, x
in enumerate(positions):
113 R_ablative_outer[i] = R_gas[i] + ablative_thickness
115 R_ablative_outer[i] = R_gas[i]
117 R_ablative_outer = R_gas.copy()
120 if graphite_config
and graphite_config.enabled:
121 graphite_axial_half_length = getattr(graphite_config,
'axial_half_length',
None)
122 if graphite_axial_half_length
is None or graphite_axial_half_length <= 0:
125 _gr = locals().get(
'graphite_config')
or locals().get(
'config')
126 _ratio = float(getattr(getattr(_gr,
'graphite_insert', _gr),
'axial_half_length_ratio', 0.75)
or 0.75)
127 graphite_axial_half_length = _ratio * D_throat
129 graphite_start =
max(throat_pos - graphite_axial_half_length, 0.0)
130 graphite_end =
min(throat_pos + graphite_axial_half_length, L_total)
132 graphite_thickness =
max(
133 graphite_config.initial_thickness - recession_graphite,
137 R_graphite_outer = np.zeros_like(positions)
138 for i, x
in enumerate(positions):
139 if graphite_start <= x <= graphite_end:
141 R_graphite_outer[i] = R_gas[i] + graphite_thickness
143 R_graphite_outer[i] = R_gas[i]
145 R_graphite_outer = R_gas.copy()
146 graphite_start = throat_pos
147 graphite_end = throat_pos
151 R_inner_max = np.maximum(R_ablative_outer, R_graphite_outer)
152 R_inner_max_global = np.max(R_inner_max)
155 stainless_thickness = 0.0025
158 R_stainless_constant = R_inner_max_global + stainless_thickness
159 R_stainless = np.full_like(positions, R_stainless_constant)
162 "positions": positions,
164 "R_ablative_outer": R_ablative_outer,
165 "R_graphite_outer": R_graphite_outer,
166 "R_stainless": R_stainless,
167 "throat_position": throat_pos,
168 "graphite_start": graphite_start,
169 "graphite_end": graphite_end,
170 "D_chamber": D_chamber,
171 "D_throat": D_throat,
Dict[str, np.ndarray] calculate_chamber_geometry_fixed(float L_chamber, float D_chamber, float D_throat, float L_nozzle=0.0, float expansion_ratio=10.0, Optional[AblativeCoolingConfig] ablative_config=None, Optional[GraphiteInsertConfig] graphite_config=None, float recession_chamber=0.0, float recession_graphite=0.0, int n_points=200)