1"""Propellant tank capacity helpers for flight simulation.
3Max loadable propellant mass is resolved from config — not a hardcoded fill fraction.
5 1. design_requirements.{lox,fuel}_tank_capacity_kg (explicit mass cap)
6 2. tank_volume_m3 × density × fill_factor
7 3. π r² h × density × fill_factor
9Fill factor comes from design_requirements.propellant_tank_fill_factor (default 0.90).
12from __future__
import annotations
15from typing
import Any, Optional, Tuple
17DEFAULT_PROPELLANT_TANK_FILL_FACTOR = 0.90
21 """Fill fraction of internal tank volume used for flight-sim mass caps (0–1)."""
22 dr = getattr(config,
"design_requirements",
None)
24 ff = getattr(dr,
"propellant_tank_fill_factor",
None)
29 return DEFAULT_PROPELLANT_TANK_FILL_FACTOR
38 if tank_section
is None:
39 raise ValueError(
"Tank section missing from config")
41 explicit = getattr(tank_section,
"tank_volume_m3",
None)
42 if explicit
is not None and float(explicit) > 0:
43 return float(explicit)
45 height = getattr(tank_section, height_attr,
None)
46 radius = getattr(tank_section, radius_attr,
None)
47 if height
is None or radius
is None:
49 f
"Tank volume undefined: set tank_volume_m3 or {height_attr}/{radius_attr}"
51 return float(math.pi * float(radius) ** 2 * float(height))
62 capacity_kg_attr: str,
63) -> Tuple[float, float, float, bool]:
64 """Return (max_mass_kg, volume_m3, fill_factor, used_explicit_capacity).
66 If design_requirements.{branch}_tank_capacity_kg is set, that mass is used directly
67 (fill_factor still reported for diagnostics).
71 tank_section, height_attr=height_attr, radius_attr=radius_attr
74 dr = getattr(config,
"design_requirements",
None)
75 explicit_cap: Optional[float] =
None
77 raw = getattr(dr, capacity_kg_attr,
None)
78 if raw
is not None and float(raw) > 0:
79 explicit_cap = float(raw)
81 if explicit_cap
is not None:
82 return explicit_cap, volume_m3, fill_factor,
True
84 max_mass = volume_m3 * float(density_kg_m3) * fill_factor
85 return max_mass, volume_m3, fill_factor,
False
92 density_kg_m3=density_kg_m3,
93 tank_section=getattr(config,
"lox_tank",
None),
95 radius_attr=
"lox_radius",
96 capacity_kg_attr=
"lox_tank_capacity_kg",
104 density_kg_m3=density_kg_m3,
105 tank_section=getattr(config,
"fuel_tank",
None),
107 radius_attr=
"rp1_radius",
108 capacity_kg_attr=
"fuel_tank_capacity_kg",
float resolve_propellant_tank_fill_factor(Any config)
Tuple[float, float, float, bool] resolve_lox_tank_limits(Any config, float density_kg_m3)
Tuple[float, float, float, bool] resolve_fuel_tank_limits(Any config, float density_kg_m3)
Tuple[float, float, float, bool] resolve_max_propellant_mass_kg(Any config, *, str branch, float density_kg_m3, Any tank_section, str height_attr, str radius_attr, str capacity_kg_attr)
float resolve_cylindrical_tank_volume_m3(Any tank_section, *, str height_attr, str radius_attr)