58 """Extract all optimized parameters from config."""
60 injector_type = getattr(getattr(config,
"injector",
None),
"type",
None)
61 if injector_type
is not None:
62 params[
"injector_type"] = injector_type
65 if hasattr(config,
'injector')
and config.injector.type ==
"pintle":
66 geometry = config.injector.geometry
67 if hasattr(geometry,
'fuel'):
68 params[
"d_pintle_tip"] = geometry.fuel.d_pintle_tip
69 params[
"h_gap"] = geometry.fuel.h_gap
70 if hasattr(geometry.fuel,
'd_reservoir_inner'):
71 params[
"d_reservoir_inner"] = geometry.fuel.d_reservoir_inner
72 if hasattr(geometry,
'lox'):
73 params[
"n_orifices"] = geometry.lox.n_orifices
74 params[
"d_orifice"] = geometry.lox.d_orifice
75 params[
"theta_orifice"] = geometry.lox.theta_orifice
76 elif hasattr(config,
'injector')
and config.injector.type ==
"impinging":
77 g = config.injector.geometry
78 nd = int(
min(int(g.oxidizer.n_elements), int(g.fuel.n_elements)))
79 params[
"n_doublets"] = nd
81 params[
"n_elements_O"] = int(g.oxidizer.n_elements)
82 params[
"d_jet_O"] = g.oxidizer.d_jet
83 params[
"imp_angle_O"] = g.oxidizer.impingement_angle
84 params[
"spacing_O"] = g.oxidizer.spacing
85 params[
"n_elements_F"] = int(g.fuel.n_elements)
86 params[
"d_jet_F"] = g.fuel.d_jet
87 params[
"imp_angle_F"] = g.fuel.impingement_angle
88 params[
"spacing_F"] = g.fuel.spacing
94 params[
"L_imp"] = impingement_standoff_m(
95 nd, g.oxidizer.spacing, g.fuel.spacing,
96 g.oxidizer.impingement_angle, g.fuel.impingement_angle,
102 params[
"D_pitch_O"] = nd * g.oxidizer.spacing / _math.pi
103 params[
"D_pitch_F"] = nd * g.fuel.spacing / _math.pi
104 params[
"ring_radial_offset"] = 0.5 * abs(params[
"D_pitch_O"] - params[
"D_pitch_F"])
106 params[
"included_angle_deg"] = float(g.oxidizer.impingement_angle) + float(g.fuel.impingement_angle)
107 params[
"jet_angle_asymmetry_deg"] = abs(
108 float(g.fuel.impingement_angle) - float(g.oxidizer.impingement_angle))
110 params[
"d_jet_oxidizer"] = g.oxidizer.d_jet
111 params[
"impingement_angle_oxidizer"] = g.oxidizer.impingement_angle
112 params[
"spacing_oxidizer"] = g.oxidizer.spacing
113 params[
"d_jet_fuel"] = g.fuel.d_jet
114 params[
"impingement_angle_fuel"] = g.fuel.impingement_angle
115 params[
"spacing_fuel"] = g.fuel.spacing
119 cg = ensure_chamber_geometry(config)
120 params[
"A_throat"] = cg.A_throat
121 params[
"Lstar"] = cg.Lstar
122 params[
"chamber_volume"] = cg.volume
123 params[
"chamber_length"] = cg.length
124 params[
"chamber_diameter"] = cg.chamber_diameter
127 params[
"A_exit"] = cg.A_exit
128 params[
"expansion_ratio"] = cg.expansion_ratio
131 if hasattr(config,
'ablative_cooling')
and config.ablative_cooling
and config.ablative_cooling.enabled:
132 params[
"ablative_thickness"] = config.ablative_cooling.initial_thickness
133 params[
"ablative_enabled"] =
True
135 params[
"ablative_thickness"] = 0.0
136 params[
"ablative_enabled"] =
False
139 if hasattr(config,
'graphite_insert')
and config.graphite_insert
and config.graphite_insert.enabled:
140 params[
"graphite_thickness"] = config.graphite_insert.initial_thickness
141 params[
"graphite_enabled"] =
True
143 params[
"graphite_thickness"] = 0.0
144 params[
"graphite_enabled"] =
False
150 config: PintleEngineConfig,
152 max_chamber_outer_diameter_m: float,
153 wall_thickness_m: float = DEFAULT_IMPINGING_WALL_THICKNESS_M,
155 """Bore used for impinging packing / n_elements limits.
157 Prefer ``chamber_geometry.chamber_diameter``; else frozen outer diameter minus wall;
158 else legacy heuristic ``0.5 * max_od - wall`` (underestimates full-OD designs).
160 cg = getattr(config,
"chamber_geometry",
None)
162 d = getattr(cg,
"chamber_diameter",
None)
163 if d
is not None and float(d) > 0.0:
165 dr = getattr(config,
"design_requirements",
None)
167 fp = getattr(dr,
"frozen_parameters",
None)
169 domm = getattr(fp,
"D_chamber_outer_mm",
None)
170 if domm
is not None and float(domm) > 0.0:
171 return float(domm) * 1e-3 - wall_thickness_m
172 min_outer = float(max_chamber_outer_diameter_m) * 0.5
173 return float(
max(min_outer - wall_thickness_m, 0.02))
177 chamber_inner_diameter_m: float,
179 pitch_est_m: float = IMPINGING_JET_PITCH_ESTIMATE_M,
180 absolute_cap: int = IMPINGING_N_ELEMENTS_ABSOLUTE_CAP,
182 """Upper integer count ~ circumference / pitch, capped for optimizer stability."""
183 if chamber_inner_diameter_m <= 0.0:
185 n_circ = int(np.pi * chamber_inner_diameter_m /
max(pitch_est_m, 1e-9))
186 return int(
max(12,
min(absolute_cap, n_circ)))