Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 21 additions & 27 deletions EngineDesign/backend/routers/flight.py
Original file line number Diff line number Diff line change
Expand Up @@ -342,14 +342,8 @@ def build_flight_config(base_config, request: FlightSimRequest):
config_dict["environment"]["date"] = request.environment.date
config_dict["environment"]["atmosphere_model"] = request.environment.atmosphere_model
elif config_dict.get("environment") is None:
# Set defaults
config_dict["environment"] = {
"latitude": 35.0,
"longitude": -117.0,
"elevation": 0.0,
"date": [2025, 1, 1, 12],
"atmosphere_model": "standard_atmosphere",
}
# No launch site anywhere: the request model's defaults, stated once, up in EnvironmentConfig.
config_dict["environment"] = EnvironmentConfig().model_dump()

# Update rocket
if request.rocket:
Expand Down Expand Up @@ -379,20 +373,20 @@ def build_flight_config(base_config, request: FlightSimRequest):
"fin_position": request.rocket.fins.fin_position,
}
elif config_dict.get("rocket") is None:
# Set defaults
# No vehicle anywhere: derive from the request model's defaults so this block cannot drift
# from RocketConfig (the literal copy that used to sit here said propulsion_dry_mass 24 kg
# while its own component defaults summed to 16).
rd = RocketConfig()
config_dict["rocket"] = {
"airframe_mass": 78.72,
"propulsion_dry_mass": 24.0,
"radius": 0.1015,
"motor_position": 0.0,
"inertia": [8.0, 8.0, 0.5],
"fins": {
"no_fins": 3,
"root_chord": 0.2,
"tip_chord": 0.1,
"fin_span": 0.3,
"fin_position": 0.1,
},
"airframe_mass": rd.airframe_mass,
"propulsion_dry_mass": rd.engine_mass + rd.lox_tank_structure_mass + rd.fuel_tank_structure_mass,
"radius": rd.radius,
"motor_position": rd.motor_position,
"inertia": list(rd.inertia),
"nose_kind": rd.nose_kind,
"nose_fineness_ratio": rd.nose_fineness_ratio,
"avionics_payload_length_m": rd.avionics_payload_length_m,
"fins": FinsConfig().model_dump(),
}

return config_dict
Expand Down Expand Up @@ -424,39 +418,39 @@ def _apply_propellant_mass_caps(config_dict: dict, base_config) -> tuple[dict, d
lox_tank_max = lox_max
fill_factor = lox_ff
current_lox = float(config_dict.get("lox_tank", {}).get("mass", 0) or 0)
effective = min(current_lox, lox_max) if current_lox > lox_max else current_lox
effective = min(current_lox, lox_max)
if current_lox > lox_max:
config_dict["lox_tank"]["mass"] = lox_max
cap_note = "explicit capacity" if lox_explicit else f"{lox_ff * 100:.0f}% fill"
print(f"[Flight] Capped LOX mass: {current_lox:.2f} -> {lox_max:.2f} kg ({cap_note}, vol {lox_vol * 1000:.1f}L)")
mass_adjustments["lox"] = {
"original": current_lox,
"capped": effective if current_lox <= lox_max else lox_max,
"capped": effective,
"max_fill_kg": lox_max,
"tank_volume_m3": lox_vol,
"fill_factor": lox_ff,
"was_capped": current_lox > lox_max + 1e-6,
"explicit_capacity_kg": lox_explicit,
"explicit_capacity_kg": lox_max if lox_explicit else None,
}

if cap_config.fuel_tank is not None:
fuel_max, fuel_vol, fuel_ff, fuel_explicit = resolve_fuel_tank_limits(cap_config, fuel_density)
fuel_tank_max = fuel_max
fill_factor = fuel_ff
current_fuel = float(config_dict.get("fuel_tank", {}).get("mass", 0) or 0)
effective = min(current_fuel, fuel_max) if current_fuel > fuel_max else current_fuel
effective = min(current_fuel, fuel_max)
if current_fuel > fuel_max:
config_dict["fuel_tank"]["mass"] = fuel_max
cap_note = "explicit capacity" if fuel_explicit else f"{fuel_ff * 100:.0f}% fill"
print(f"[Flight] Capped Fuel mass: {current_fuel:.2f} -> {fuel_max:.2f} kg ({cap_note}, vol {fuel_vol * 1000:.1f}L)")
mass_adjustments["fuel"] = {
"original": current_fuel,
"capped": effective if current_fuel <= fuel_max else fuel_max,
"capped": effective,
"max_fill_kg": fuel_max,
"tank_volume_m3": fuel_vol,
"fill_factor": fuel_ff,
"was_capped": current_fuel > fuel_max + 1e-6,
"explicit_capacity_kg": fuel_explicit,
"explicit_capacity_kg": fuel_max if fuel_explicit else None,
}

return mass_adjustments, lox_tank_max, fuel_tank_max, fill_factor
Expand Down
7 changes: 6 additions & 1 deletion EngineDesign/configs/canonical/impinging.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,17 @@ feed_system:
# under-predicted LOX feed loss by ~3.8x (dP ~ 1/A^2).
fuel:
line_size: 3/8_NPT
# Tank outlet to injector manifold. Sets the chug-model line inertance (length/area);
# 0.305 m is the value the model used to carry hardcoded -- measure it on the vehicle.
length: 0.305
K0: 2.0
K1: 0.0
phi_type: none
oxidizer:
line_size: 3/8_NPT
# Tank outlet to injector manifold. Sets the chug-model line inertance (length/area);
# 0.305 m is the value the model used to carry hardcoded -- measure it on the vehicle.
length: 0.305
K0: 2.0
K1: 0.0
phi_type: none
Expand Down Expand Up @@ -67,7 +73,6 @@ regen_cooling:
n_segments: 20
gas_turbulence_intensity: 0.1
coolant_turbulence_intensity: 0.05
hot_gas_cp: 2200.0
recovery_factor: null
film_cooling:
enabled: false
Expand Down
9 changes: 7 additions & 2 deletions EngineDesign/configs/canonical/pintle.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ chamber_geometry:
Cf: 1.5422822280584674
Lstar: 1.239905396733828
chamber_diameter: 0.11344154349849075
design_MR: 2.55
design_MR: 1.4
design_pressure: 2413166.0
design_thrust: 7000.0
exit_diameter: 0.101
Expand Down Expand Up @@ -173,11 +173,17 @@ feed_system:
# under-predicted LOX feed loss by ~3.8x (dP ~ 1/A^2).
fuel:
line_size: 3/8_NPT
# Tank outlet to injector manifold. Sets the chug-model line inertance (length/area);
# 0.305 m is the value the model used to carry hardcoded -- measure it on the vehicle.
length: 0.305
K0: 2.0
K1: 0.0
phi_type: none
oxidizer:
line_size: 3/8_NPT
# Tank outlet to injector manifold. Sets the chug-model line inertance (length/area);
# 0.305 m is the value the model used to carry hardcoded -- measure it on the vehicle.
length: 0.305
K0: 2.0
K1: 0.0
phi_type: none
Expand Down Expand Up @@ -421,7 +427,6 @@ regen_cooling:
d_outlet: null
enabled: false
gas_turbulence_intensity: 0.1
hot_gas_cp: 2200.0
hot_gas_prandtl: 0.7
hot_gas_thermal_conductivity: 0.12
hot_gas_viscosity: 4.0e-05
Expand Down
7 changes: 6 additions & 1 deletion EngineDesign/configs/default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,17 @@ feed_system:
# under-predicted LOX feed loss by ~3.8x (dP ~ 1/A^2).
fuel:
line_size: 3/8_NPT
# Tank outlet to injector manifold. Sets the chug-model line inertance (length/area);
# 0.305 m is the value the model used to carry hardcoded -- measure it on the vehicle.
length: 0.305
K0: 2.0
K1: 0.0
phi_type: none
oxidizer:
line_size: 3/8_NPT
# Tank outlet to injector manifold. Sets the chug-model line inertance (length/area);
# 0.305 m is the value the model used to carry hardcoded -- measure it on the vehicle.
length: 0.305
K0: 2.0
K1: 0.0
phi_type: none
Expand Down Expand Up @@ -84,7 +90,6 @@ regen_cooling:
n_segments: 20
gas_turbulence_intensity: 0.1
coolant_turbulence_intensity: 0.05
hot_gas_cp: 2200.0
recovery_factor: null
film_cooling:
enabled: false
Expand Down
1 change: 0 additions & 1 deletion EngineDesign/configs/impinging_lox_ch4.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,6 @@ regen_cooling:
d_outlet: null
enabled: false
gas_turbulence_intensity: 0.1
hot_gas_cp: 2200.0
hot_gas_prandtl: 0.7
hot_gas_thermal_conductivity: 0.12
hot_gas_viscosity: 4.0e-05
Expand Down
1 change: 0 additions & 1 deletion EngineDesign/configs/impinging_lox_ch4_8000N.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,6 @@ regen_cooling:
d_outlet: null
enabled: false
gas_turbulence_intensity: 0.1
hot_gas_cp: 2200.0
hot_gas_prandtl: 0.7
hot_gas_thermal_conductivity: 0.12
hot_gas_viscosity: 4.0e-05
Expand Down
1 change: 0 additions & 1 deletion EngineDesign/configs/impinging_lox_ch4_8000N_optimal.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ regen_cooling:
n_segments: 20
gas_turbulence_intensity: 0.1
coolant_turbulence_intensity: 0.05
hot_gas_cp: 2200.0
recovery_factor: null
film_cooling:
enabled: false
Expand Down
1 change: 0 additions & 1 deletion EngineDesign/configs/impinging_smoke.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ regen_cooling:
n_segments: 20
gas_turbulence_intensity: 0.1
coolant_turbulence_intensity: 0.05
hot_gas_cp: 2200.0
recovery_factor: null
film_cooling:
enabled: false
Expand Down
1 change: 0 additions & 1 deletion EngineDesign/configs/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ regen_cooling:
n_segments: 20
gas_turbulence_intensity: 0.1
coolant_turbulence_intensity: 0.05
hot_gas_cp: 2200.0
recovery_factor: null
film_cooling:
enabled: false
Expand Down
64 changes: 27 additions & 37 deletions EngineDesign/engine/accel/kernels.py
Original file line number Diff line number Diff line change
Expand Up @@ -966,8 +966,11 @@ def _solve_exit_mach(eps, g):
@njit(cache=True)
def evaluate_core(P, Pcg, MRg, epsg, cstar, Cf, Tc_t, gam, Rt, Mt, Cfv, P_O, P_F, Pa):
"""Returns (ok, Pc, F, Isp, MR, cstar_actual, gamma, Tc, mdot_total, v_exit, Cf_actual)."""
Pc_min = 100000.0
Pc_max = min(P_O, P_F)*(1.0 - 0.15)
# Search window and bracket scan: VERBATIM mirror of engine/core/chamber_solver.py
# (PC_CHOKE_FLOOR_PA, PC_MIN_TOTAL_DROP_FRAC, ChamberSolver._highest_sign_change). The parity
# gate requires the two root-finds to agree, so change both or neither.
Pc_min = 2.0*101325.0
Pc_max = min(P_O, P_F)*(1.0 - 0.02)
Pc_min = max(Pc_min, P[SV_PCMIN]); Pc_max = min(Pc_max, P[SV_PCMAX])
if Pc_max <= Pc_min:
return (0.0,)*22
Expand All @@ -976,41 +979,28 @@ def evaluate_core(P, Pcg, MRg, epsg, cstar, Cf, Tc_t, gam, Rt, Mt, Cfv, P_O, P_F
rmax = _residual(Pc_max, P, Pcg, MRg, epsg, cstar, Cf, Tc_t, gam, Rt, Mt, Cfv, P_O, P_F)
if not np.isfinite(rmin) or not np.isfinite(rmax):
return (0.0,)*22
if _sign(rmin) == _sign(rmax):
# The residual is not always monotonic in Pc: on the canonical impinging design at
# asymmetric tank pressures it is NEGATIVE at Pc_min, turns POSITIVE mid-range, and goes
# negative again by Pc_max, so an endpoint-only sign test sees "no root" and bails where
# a root plainly exists (measured: -0.214 at 1.0 bar, +0.76 at 20 bar, -0.96 at 27.4 bar,
# root at 23.75 bar). Scan for a sign-changing sub-interval before giving up -- the pure
# Python solver finds these, and the parity gate requires the accelerator to agree.
# Scan from the HIGH end down: a non-monotonic residual can also cross near Pc_min
# (a spurious low-pressure crossing where the chamber is barely flowing). The physical
# operating point is the HIGHEST-Pc root, which is the one the pure Python solver
# converges to; taking the first crossing from the bottom picked the spurious one and
# diverged from Python by 3.3x.
_n = 32
_lo = 0.0; _hi = 0.0; _found = False
_pb = Pc_max; _rb = rmax
for _i in range(_n - 1, -1, -1):
_pa = Pc_min + (Pc_max - Pc_min)*(_i/_n)
_ra = _residual(_pa, P, Pcg, MRg, epsg, cstar, Cf, Tc_t, gam, Rt, Mt, Cfv, P_O, P_F)
if np.isfinite(_ra) and np.isfinite(_rb) and _sign(_ra) != _sign(_rb):
_lo = _pa; _hi = _pb; _found = True
break
_pb = _pa; _rb = _ra
if _found:
Pc = _brentq(P, Pcg, MRg, epsg, cstar, Cf, Tc_t, gam, Rt, Mt, Cfv, P_O, P_F,
_lo, _hi, xtol, rtol, maxit)
if not np.isfinite(Pc):
return (0.0,)*22
elif rmin > 0 and rmax > 0 and rmax < 0.1:
Pc = Pc_max
else:
return (0.0,)*22
else:
Pc = _brentq(P, Pcg, MRg, epsg, cstar, Cf, Tc_t, gam, Rt, Mt, Cfv, P_O, P_F, Pc_min, Pc_max, xtol, rtol, maxit)
if not np.isfinite(Pc):
return (0.0,)*22
# The residual is not monotonic in Pc: it is negative near the choking floor (barely flowing,
# the spurious crossing), positive through the operating range, and negative again once the
# injector drop gets small. The physical operating point is the HIGHEST-Pc root, so scan from
# Pc_max down for the first sign change and bracket Brent inside it. Endpoint-only tests
# missed interior roots (measured on canonical/impinging: -0.214 at 1 bar, +0.76 at 20 bar,
# -0.96 at 27.4 bar, root at 23.75 bar) and a whole-window Brent picked the spurious low one.
_n = 32
_lo = 0.0; _hi = 0.0; _found = False
_pb = Pc_max; _rb = rmax
for _i in range(_n - 1, -1, -1):
_pa = Pc_min + (Pc_max - Pc_min)*(_i/_n)
_ra = rmin if _i == 0 else _residual(_pa, P, Pcg, MRg, epsg, cstar, Cf, Tc_t, gam, Rt, Mt, Cfv, P_O, P_F)
if np.isfinite(_ra) and np.isfinite(_rb) and _sign(_ra) != _sign(_rb):
_lo = _pa; _hi = _pb; _found = True
break
_pb = _pa; _rb = _ra
if not _found:
return (0.0,)*22
Pc = _brentq(P, Pcg, MRg, epsg, cstar, Cf, Tc_t, gam, Rt, Mt, Cfv, P_O, P_F,
_lo, _hi, xtol, rtol, maxit)
if not np.isfinite(Pc):
return (0.0,)*22
# recompute converged state
(ok, mO, mF, uO, uF, D32O, D32F, momR, CdO, CdF, PiO, PiF, dpiO, dpiF, AgO, AgF,
dpfO, dpfF, WeO, WeF, urel, xstar, constr, nit, tiO, tiF) = _solve_injector(P, P_O, P_F, Pc)
Expand Down
9 changes: 9 additions & 0 deletions EngineDesign/engine/control/robust_ddp/data_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,15 @@ class ControllerConfig:
# Regulator model
reg_setpoint: Optional[float] = None # Regulator setpoint [Pa] (None = derived from COPV)
reg_ratio: float = 0.8 # P_reg / P_copv ratio if setpoint not specified
# Pressurisation-path hardware. Previously literals inside dynamics.step(); surfaced here so
# a vehicle with a different regulator or solenoid can be modelled without editing code.
# See docs/adr/0001 -- this chain is one of the feed models lib/feedtwin absorbs.
gamma_gas: float = 1.4 # Pressurant specific heat ratio (N2)
Cd_regulator: float = 0.7 # Discharge coefficient, regulator orifice
Cd_valve: float = 0.65 # Discharge coefficient, solenoid valve orifice
A_regulator: float = 2e-5 # Regulator orifice area [m^2]
A_valve_F: float = 5e-5 # Fuel solenoid valve flow area [m^2]
A_valve_O: float = 5e-5 # Oxidiser solenoid valve flow area [m^2]

# Ullage pressurization flow coefficients [1/s]
alpha_F: float = 10.0 # Fuel pressurization flow coefficient
Expand Down
Loading
Loading