STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
tank_capacity.py
Go to the documentation of this file.
1"""Propellant tank capacity helpers for flight simulation.
2
3Max loadable propellant mass is resolved from config — not a hardcoded fill fraction.
4Priority:
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
8
9Fill factor comes from design_requirements.propellant_tank_fill_factor (default 0.90).
10"""
11
12from __future__ import annotations
13
14import math
15from typing import Any, Optional, Tuple
16
17DEFAULT_PROPELLANT_TANK_FILL_FACTOR = 0.90
18
19
20def resolve_propellant_tank_fill_factor(config: Any) -> float:
21 """Fill fraction of internal tank volume used for flight-sim mass caps (0–1)."""
22 dr = getattr(config, "design_requirements", None)
23 if dr is not None:
24 ff = getattr(dr, "propellant_tank_fill_factor", None)
25 if ff is not None:
26 val = float(ff)
27 if 0.0 < val <= 1.0:
28 return val
29 return DEFAULT_PROPELLANT_TANK_FILL_FACTOR
30
31
33 tank_section: Any,
34 *,
35 height_attr: str,
36 radius_attr: str,
37) -> float:
38 if tank_section is None:
39 raise ValueError("Tank section missing from config")
40
41 explicit = getattr(tank_section, "tank_volume_m3", None)
42 if explicit is not None and float(explicit) > 0:
43 return float(explicit)
44
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:
48 raise ValueError(
49 f"Tank volume undefined: set tank_volume_m3 or {height_attr}/{radius_attr}"
50 )
51 return float(math.pi * float(radius) ** 2 * float(height))
52
53
55 config: Any,
56 *,
57 branch: str,
58 density_kg_m3: float,
59 tank_section: Any,
60 height_attr: str,
61 radius_attr: str,
62 capacity_kg_attr: str,
63) -> Tuple[float, float, float, bool]:
64 """Return (max_mass_kg, volume_m3, fill_factor, used_explicit_capacity).
65
66 If design_requirements.{branch}_tank_capacity_kg is set, that mass is used directly
67 (fill_factor still reported for diagnostics).
68 """
69 fill_factor = resolve_propellant_tank_fill_factor(config)
71 tank_section, height_attr=height_attr, radius_attr=radius_attr
72 )
73
74 dr = getattr(config, "design_requirements", None)
75 explicit_cap: Optional[float] = None
76 if dr is not None:
77 raw = getattr(dr, capacity_kg_attr, None)
78 if raw is not None and float(raw) > 0:
79 explicit_cap = float(raw)
80
81 if explicit_cap is not None:
82 return explicit_cap, volume_m3, fill_factor, True
83
84 max_mass = volume_m3 * float(density_kg_m3) * fill_factor
85 return max_mass, volume_m3, fill_factor, False
86
87
88def resolve_lox_tank_limits(config: Any, density_kg_m3: float) -> Tuple[float, float, float, bool]:
90 config,
91 branch="lox",
92 density_kg_m3=density_kg_m3,
93 tank_section=getattr(config, "lox_tank", None),
94 height_attr="lox_h",
95 radius_attr="lox_radius",
96 capacity_kg_attr="lox_tank_capacity_kg",
97 )
98
99
100def resolve_fuel_tank_limits(config: Any, density_kg_m3: float) -> Tuple[float, float, float, bool]:
102 config,
103 branch="fuel",
104 density_kg_m3=density_kg_m3,
105 tank_section=getattr(config, "fuel_tank", None),
106 height_attr="rp1_h",
107 radius_attr="rp1_radius",
108 capacity_kg_attr="fuel_tank_capacity_kg",
109 )
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)