|
STAR
Cal STAR — firmware, DAQ server, and engine design
|
Public Member Functions | |
| float | pressure (self) |
| float | outlet_pressure (self) |
| None | take_back (self, float mass) |
| dict[str, float] | readouts (self) |
| bool | skip_chill (self) |
| float | load_target_kg (self) |
| float | fill_line_flow (self, float drop) |
| float | advance (self, float dt, *, float mdot_liquid_out, float mdot_gas_in, float mdot_gas_out, float enthalpy_gas_in, float supply_pressure=0.0, float stirring=1.0, float vent_fraction=1.0, float mdot_liquid_in=0.0, float|None liquid_in_temperature=None) |
Public Attributes | |
| state | |
| pressure | |
Static Public Attributes | |
| bool | filling = False |
| bool | empty = False |
| float | fill_seconds = 30.0 |
| float | chill_seconds = 0.0 |
| bool | chilling = False |
| float | chill_boiled = 0.0 |
| float | dewar_pressure = 0.0 |
| float | fill_line_bore = 7.75e-3 |
| float | fill_line_length = 3.0 |
| float | fill_cv = 0.019 |
| float | fill_flow = 0.0 |
| object | node = None |
| float | mawp = 0.0 |
| float | full_fraction = FULL_FRACTION |
| float | load_kg = 0.0 |
| float | charge_gamma = CHARGE_GAMMA |
| float | supply_band = SUPPLY_BAND |
| float | stir_band = STIR_BAND |
| float | gravity = GRAVITY |
| float | added_kg = 0.0 |
| float | fixed_kg = 0.0 |
| float | fixed_J = 0.0 |
| bool | sealed = False |
| float | floored_kg = 0.0 |
| float | vent_drawn_kg = 0.0 |
| float | refused_kg = 0.0 |
Protected Member Functions | |
| bool | _chill (self, float dt) |
| float | _chill_target (self, float|None pressure=None) |
| VesselState | _chilled_ullage (self, TankState state, float wall) |
| float | _wanted (self) |
| None | _collect (self, float added) |
| bool | _dewar_load (self, float dt) |
| None | _one_step (self, float dt, float mdot_liquid_out, float net_gas, float enthalpy, float stirring=1.0, float vapour_out=0.0) |
| None | _ledger (self, TankRates rates, float dt, TankState landed, TankState|None start=None, tuple[float, float] drawn=(0.0, 0.0)) |
| float | _pressurant_floor (self, float|None wall_temperature=None) |
| float | _specific_energy_at (self, float mass, float temperature) |
| float | _gas_temperature_of (self, VesselState ullage) |
| float | _atmosphere_floor (self, VesselState|None ullage=None) |
| VesselState | _settled (self, VesselState ullage) |
Static Protected Attributes | |
| tuple | _drawn_piece = (0.0, 0.0) |
|
protected |
The pressurant that brings the tank back to atmosphere [kg]: its partial pressure the air's less what the propellant vapour already holds (Dalton, as :meth:`Tank.pressure`), at the gas's own temperature. What "a vent cannot pull a tank below the air outside it" means. The old floor (:meth:`_pressurant_floor`) asked for a whole atmosphere of pressurant at the *wall's* temperature, which only fits a tank whose ullage is the wall's own boil-off -- a built-in chill, where it stands in for that boil-off (see :meth:`_settled`).
Definition at line 1939 of file core.py.
References _gas_temperature_of(), max, anonymous_namespace{idle_e2e.cpp}::Beat.state, anonymous_namespace{idle_e2e.cpp}::World.state, battery_t.state, state, gnss_core_t.state, gnss_frame_parser_t.state, SensorHotfire::CoreState.state, Valve.state, world_t.state, and feedtwin.session.burn.BurnTrace.tank.
Referenced by _settled().
|
protected |
Spend this step's pour on the wall, if the wall still wants it. Only for a cryogen load into a tank that holds no liquid yet: what is poured flashes on the metal and goes out of the vent, so nothing collects until the wall is down at saturation for the tank's pressure (plus the boiling onset, where a wall stops boiling what touches it). The wall falls at the rate that takes it from the room to the liquid in ``chill_seconds``; the heat it gives up is the propellant flashed, ``Q / h_fg``, booked in :attr:`chill_boiled`. Returns whether the step was spent chilling.
Definition at line 1292 of file core.py.
References _chill_target(), chill_boiled, chill_seconds, max, min, anonymous_namespace{idle_e2e.cpp}::Beat.state, anonymous_namespace{idle_e2e.cpp}::World.state, battery_t.state, state, gnss_core_t.state, gnss_frame_parser_t.state, SensorHotfire::CoreState.state, Valve.state, world_t.state, and feedtwin.session.burn.BurnTrace.tank.
Referenced by advance().
|
protected |
Where a load's chilldown takes the wall [K]: saturation at the tank's pressure (or ``pressure``), plus the boiling onset, where a wall stops boiling what touches it.
Definition at line 1340 of file core.py.
References max, feedtwin.session.burn.BurnTrace.pressure, pressure, anonymous_namespace{idle_e2e.cpp}::Beat.state, anonymous_namespace{idle_e2e.cpp}::World.state, battery_t.state, state, gnss_core_t.state, gnss_frame_parser_t.state, SensorHotfire::CoreState.state, Valve.state, world_t.state, and feedtwin.session.burn.BurnTrace.tank.
Referenced by _chill(), and skip_chill().
|
protected |
The ullage a chill leaves: at the chilled wall's temperature, at the pressure it holds now. A chill floods the ullage with its own cold boil-off; skipping one cooled the metal and left the gas warm, which then chilled on the wall after the skip and pulled the tank under the air -- in the old floor, 39.6 g of nitrogen in one step (2026-10-12). The gas the colder ullage holds is the boil-off a chill would have left there, from the load, and is booked as the load's (:attr:`added_kg`).
Definition at line 1393 of file core.py.
References added_kg, max, pressure, and feedtwin.session.burn.BurnTrace.tank.
Referenced by skip_chill().
|
protected |
Put ``added`` kg of the load into the liquid.
Definition at line 1432 of file core.py.
References pressure, anonymous_namespace{idle_e2e.cpp}::Beat.state, anonymous_namespace{idle_e2e.cpp}::World.state, battery_t.state, state, gnss_core_t.state, gnss_frame_parser_t.state, SensorHotfire::CoreState.state, Valve.state, world_t.state, and feedtwin.session.burn.BurnTrace.tank.
Referenced by _dewar_load(), advance(), and calibration_orchestrator.CalibrationOrchestrator.run_phase1().
|
protected |
One step of a cryogen load pushed in by the dewar. What arrives is :meth:`fill_line_flow` at the dewar's pressure less the tank's. Into a tank holding no liquid yet, with the wall above saturation for the tank's pressure (plus the boiling onset, as in :meth:`_chill`), it boils on the wall: the wall gives up ``h_fg`` for every gram, and the vapour goes into the **ullage**, where only the vent can take it out. That is the climb the stand shows while a tank chills, and why it is larger the faster the dewar pours. What arrives once the wall is cold -- or what the wall had no heat left to boil -- collects, up to the full fraction. Returns whether the step was spent chilling.
Definition at line 1496 of file core.py.
References _collect(), _wanted(), chill_boiled, dewar_pressure, fill_flow, fill_line_flow(), max, min, feedtwin.session.burn.BurnTrace.pressure, pressure, anonymous_namespace{idle_e2e.cpp}::Beat.state, anonymous_namespace{idle_e2e.cpp}::World.state, battery_t.state, state, gnss_core_t.state, gnss_frame_parser_t.state, SensorHotfire::CoreState.state, Valve.state, world_t.state, and feedtwin.session.burn.BurnTrace.tank.
Referenced by advance().
|
protected |
The pressurant's own temperature in ``ullage`` [K]; the wall's when it cannot be priced.
Definition at line 1922 of file core.py.
References max, anonymous_namespace{idle_e2e.cpp}::Beat.state, anonymous_namespace{idle_e2e.cpp}::World.state, battery_t.state, state, gnss_core_t.state, gnss_frame_parser_t.state, SensorHotfire::CoreState.state, Valve.state, world_t.state, and feedtwin.session.burn.BurnTrace.tank.
Referenced by _atmosphere_floor(), and _settled().
|
protected |
Book what the guards changed: where a piece of step ``landed`` against where the rates over its ``dt`` said it would. Air an open vent let in (``drawn``, kg and J, from :meth:`_settled`) crossed the boundary: it is booked as in, not as a clamp.
Definition at line 1863 of file core.py.
References added_kg, fixed_J, fixed_kg, anonymous_namespace{idle_e2e.cpp}::Beat.state, anonymous_namespace{idle_e2e.cpp}::World.state, battery_t.state, state, gnss_core_t.state, gnss_frame_parser_t.state, SensorHotfire::CoreState.state, Valve.state, world_t.state, and vent_drawn_kg.
Referenced by _one_step().
|
protected |
One vessel step that lands somewhere the gas can actually be. Halves itself and retries when it does not. An explicit step onto a small ullage during a vent can overshoot into a state the equation of state refuses -- correctly, since it is a solid -- and the alternative to retrying is the run dying at the moment it is meant to demonstrate. Halving shortens the piece, never the step: once a piece lands, the next one starts from it, until all of ``dt`` is integrated. Returning on the first piece that landed -- what this did -- dropped the rest of the step's liquid outflow, gas exchange and heat every time a vent forced a retry. The pieces are counted in whole ``dt / 2**halvings`` so they sum to ``dt`` exactly; with no retry it is one piece of ``dt``, as before.
Definition at line 1777 of file core.py.
References _drawn_piece, _ledger(), _settled(), max, pressure, anonymous_namespace{idle_e2e.cpp}::Beat.state, anonymous_namespace{idle_e2e.cpp}::World.state, battery_t.state, state, gnss_core_t.state, gnss_frame_parser_t.state, SensorHotfire::CoreState.state, Valve.state, world_t.state, and feedtwin.session.burn.BurnTrace.tank.
Referenced by advance().
|
protected |
The least pressurant the ullage holds [kg]: atmosphere's worth at the wall, in the ullage's present volume (see :meth:`_settled`).
Definition at line 1891 of file core.py.
References max, anonymous_namespace{idle_e2e.cpp}::Beat.state, anonymous_namespace{idle_e2e.cpp}::World.state, battery_t.state, state, gnss_core_t.state, gnss_frame_parser_t.state, SensorHotfire::CoreState.state, Valve.state, world_t.state, and feedtwin.session.burn.BurnTrace.tank.
Referenced by _settled(), and advance().
|
protected |
Keep the ullage inside the states the gas can actually occupy. Two floors, and both are physics rather than numerics. A vent cannot pull a tank below the air outside it, so the **mass** cannot fall below what atmosphere would hold in that volume. Only with a vent: a :attr:`sealed` tank has nothing to let air in, and goes below atmosphere as its liquid drains. The floor is on the pressurant alone because the pressurant carries the ullage's heat capacity: the propellant vapour has no energy term (see ``Tank.rates``), so an ullage vented down to vapour alone would have no thermal mass to integrate. What keeps the floor from *creating* gas is the vent's split (:meth:`advance`): once the pressurant is at its floor the vent takes vapour, which is what a tank chilling down under its own boil-off is venting. Only the mass, deliberately. Chilling is bounded by sizing the step against the energy leaving (see MAX_ENERGY_FRACTION) rather than by clamping the temperature afterwards: a clamp applied every sub-step is a ratchet that puts energy *in*, and a venting tank then climbs in pressure instead of falling.
Definition at line 1962 of file core.py.
References _atmosphere_floor(), _drawn_piece, _gas_temperature_of(), _pressurant_floor(), _specific_energy_at(), chilling, floored_kg, max, min, pressure, sealed, anonymous_namespace{idle_e2e.cpp}::Beat.state, anonymous_namespace{idle_e2e.cpp}::World.state, battery_t.state, state, gnss_core_t.state, gnss_frame_parser_t.state, SensorHotfire::CoreState.state, Valve.state, world_t.state, and feedtwin.session.burn.BurnTrace.tank.
Referenced by _one_step().
|
protected |
The pressurant's specific internal energy [J/kg] as ``mass`` of it fills the ullage at ``temperature``: at its own partial density, which is what :meth:`_gas_temperature_of` reads it back at. Priced at a whole atmosphere instead, a floored ullage sharing the tank with propellant vapour came back colder than it was restated at -- nitrogen near its dew line is far from ideal, ~1 K at 85 K between one atmosphere and half of one -- and each floored step ratcheted it down: a vented LOX load took its ullage to nitrogen's 77 K boiling point over 90 K liquid and a 92 K wall.
Definition at line 1902 of file core.py.
References max, anonymous_namespace{idle_e2e.cpp}::Beat.state, anonymous_namespace{idle_e2e.cpp}::World.state, battery_t.state, state, gnss_core_t.state, gnss_frame_parser_t.state, SensorHotfire::CoreState.state, Valve.state, world_t.state, and feedtwin.session.burn.BurnTrace.tank.
Referenced by _settled().
|
protected |
Liquid mass a load stops at [kg]: the fire load when there is one, never more than the full fraction of the tank.
Definition at line 1425 of file core.py.
References feedtwin.session.core.Setup.full_fraction, full_fraction, load_kg, min, anonymous_namespace{idle_e2e.cpp}::Beat.state, anonymous_namespace{idle_e2e.cpp}::World.state, battery_t.state, state, gnss_core_t.state, gnss_frame_parser_t.state, SensorHotfire::CoreState.state, Valve.state, world_t.state, and feedtwin.session.burn.BurnTrace.tank.
Referenced by _dewar_load(), advance(), and load_target_kg().
| float feedtwin.session.core.TankSim.advance | ( | self, | |
| float | dt, | ||
| * | , | ||
| float | mdot_liquid_out, | ||
| float | mdot_gas_in, | ||
| float | mdot_gas_out, | ||
| float | enthalpy_gas_in, | ||
| float | supply_pressure = 0.0, | ||
| float | stirring = 1.0, | ||
| float | vent_fraction = 1.0, | ||
| float | mdot_liquid_in = 0.0, | ||
| float | None | liquid_in_temperature = None ) |
One vessel step, with the flows the network just produced. ``mdot_liquid_in`` is propellant the network delivers to this tank's outlet from another tank -- a cart's transfer tank loading it -- arriving at ``liquid_in_temperature`` and mixed into the liquid. It squeezes the ullage as it comes in, which ``Tank.rates`` prices as the p dV work the drain does in reverse. Returns the gas inflow it **refused** [kg/s]. The caller owes that back to whatever was debited for it: the network solved a flow leaving the bottle, and if the tank does not take it, it did not happen. In and out are separate, not netted. They are simultaneous during a fill -- pressurant on one port, vent on another -- and they carry different energy: gas arriving brings the supply's enthalpy, gas leaving takes the ullage's own. Netting them would price the whole exchange at the supply's enthalpy and make a venting tank warm up.
Definition at line 1558 of file core.py.
References _chill(), _collect(), _dewar_load(), _one_step(), _pressurant_floor(), _wanted(), added_kg, feedtwin.session.core.Setup.charge_gamma, charge_gamma, chilling, dewar_pressure, empty, fill_flow, fill_seconds, filling, fixed_kg, max, min, feedtwin.session.burn.BurnTrace.pressure, pressure, anonymous_namespace{idle_e2e.cpp}::Beat.state, anonymous_namespace{idle_e2e.cpp}::World.state, battery_t.state, state, gnss_core_t.state, gnss_frame_parser_t.state, SensorHotfire::CoreState.state, Valve.state, world_t.state, feedtwin.session.core.Setup.stir_band, stir_band, feedtwin.session.core.Setup.supply_band, supply_band, and feedtwin.session.burn.BurnTrace.tank.
| float feedtwin.session.core.TankSim.fill_line_flow | ( | self, | |
| float | drop ) |
What the dewar's fill line passes at a pressure drop [kg/s]. Liquid through the line: ``drop = (f L / D + K_valves + 1) rho v^2 / 2``, the 1 being the exit into the tank, ``K_valves`` from the Cv of what on the line is not tube (``fluids.fittings.Cv_to_K``), and ``f`` Clamond at the Reynolds number the flow itself sets -- iterated, since the flow sets it. Nothing flows back into the dewar.
Definition at line 1464 of file core.py.
References fill_cv, fill_line_bore, fill_line_length, anonymous_namespace{idle_e2e.cpp}::Beat.state, anonymous_namespace{idle_e2e.cpp}::World.state, battery_t.state, state, gnss_core_t.state, gnss_frame_parser_t.state, SensorHotfire::CoreState.state, Valve.state, world_t.state, and feedtwin.session.burn.BurnTrace.tank.
Referenced by _dewar_load().
| float feedtwin.session.core.TankSim.load_target_kg | ( | self | ) |
| float feedtwin.session.core.TankSim.outlet_pressure | ( | self | ) |
Definition at line 1243 of file core.py.
References feedtwin.comps.base.FlowConditions.gravity, gravity, outlet_pressure(), anonymous_namespace{idle_e2e.cpp}::Beat.state, anonymous_namespace{idle_e2e.cpp}::World.state, battery_t.state, state, gnss_core_t.state, gnss_frame_parser_t.state, SensorHotfire::CoreState.state, Valve.state, world_t.state, and feedtwin.session.burn.BurnTrace.tank.
Referenced by outlet_pressure().
| float feedtwin.session.core.TankSim.pressure | ( | self | ) |
Definition at line 1239 of file core.py.
Referenced by feedtwin.session.core.BottleSim.advance(), feedtwin.session.core.BottleSim.fraction(), feedtwin.vessels.tank.Tank.outlet_pressure(), feedtwin.vessels.tank.Tank.pressurant_for_expulsion(), and feedtwin.vessels.tank.Tank.rates().
| dict[str, float] feedtwin.session.core.TankSim.readouts | ( | self | ) |
| bool feedtwin.session.core.TankSim.skip_chill | ( | self | ) |
Put the wall where a chilldown leaves it, now. Where it leaves it once the boil-off has vented: the chill target at atmosphere (or at the tank's pressure, if lower). Not at the tank's present pressure -- a chilling tank sits above atmosphere on its own boil-off, that pressure falls as soon as the boiling stops, and a wall left at its saturation is above the new one a moment later and chilling again. What the metal gave up is the propellant the chill flashes off and vents, booked in :attr:`chill_boiled`; a load then collects from its next step. Returns whether there was anything to chill: not for a liquid that is no cryogen, nor a wall already there.
Definition at line 1352 of file core.py.
References _chill_target(), _chilled_ullage(), chill_boiled, chilling, max, min, feedtwin.session.burn.BurnTrace.pressure, pressure, anonymous_namespace{idle_e2e.cpp}::Beat.state, anonymous_namespace{idle_e2e.cpp}::World.state, battery_t.state, state, gnss_core_t.state, gnss_frame_parser_t.state, SensorHotfire::CoreState.state, Valve.state, world_t.state, and feedtwin.session.burn.BurnTrace.tank.
| None feedtwin.session.core.TankSim.take_back | ( | self, | |
| float | mass ) |
Return pressurant this ullage sent out that no vessel took [kg]. It left booked at the ullage's enthalpy, so it comes back at it: the exact reverse of the debit in :meth:`advance`.
Definition at line 1246 of file core.py.
References anonymous_namespace{idle_e2e.cpp}::Beat.state, anonymous_namespace{idle_e2e.cpp}::World.state, battery_t.state, state, gnss_core_t.state, gnss_frame_parser_t.state, SensorHotfire::CoreState.state, Valve.state, world_t.state, and feedtwin.session.burn.BurnTrace.tank.
|
staticprotected |
Definition at line 1233 of file core.py.
Referenced by _one_step(), and _settled().
|
static |
Definition at line 1218 of file core.py.
Referenced by _chilled_ullage(), _ledger(), feedtwin.session.core.BottleSim.advance(), and advance().
|
static |
|
static |
Definition at line 1187 of file core.py.
Referenced by _chill(), _dewar_load(), and skip_chill().
|
static |
|
static |
Definition at line 1185 of file core.py.
Referenced by _settled(), advance(), and skip_chill().
|
static |
Definition at line 1190 of file core.py.
Referenced by _dewar_load(), and advance().
|
static |
|
static |
Definition at line 1195 of file core.py.
Referenced by fill_line_flow().
|
static |
Definition at line 1197 of file core.py.
Referenced by _dewar_load(), and advance().
|
static |
Definition at line 1193 of file core.py.
Referenced by fill_line_flow().
|
static |
Definition at line 1194 of file core.py.
Referenced by fill_line_flow().
|
static |
Definition at line 1180 of file core.py.
Referenced by feedtwin.session.core.BottleSim.advance(), and advance().
|
static |
Definition at line 1178 of file core.py.
Referenced by feedtwin.session.core.BottleSim.advance(), and advance().
|
static |
|
static |
Definition at line 1219 of file core.py.
Referenced by _ledger(), feedtwin.session.core.BottleSim.advance(), and advance().
|
static |
Definition at line 1227 of file core.py.
Referenced by _settled().
|
static |
|
static |
Definition at line 1210 of file core.py.
Referenced by feedtwin.solve.network.Network.conditions(), and outlet_pressure().
|
static |
| feedtwin.session.core.TankSim.pressure |
Definition at line 1266 of file core.py.
Referenced by _chill_target(), _chilled_ullage(), _collect(), _dewar_load(), _one_step(), _settled(), feedtwin.session.core.BottleSim.advance(), advance(), feedtwin.session.network_trace.NetworkTrace.append(), feedtwin.session.core.BottleSim.fraction(), feedtwin.solve.network.Node.is_fixed(), feedtwin.vessels.tank.Tank.outlet_pressure(), feedtwin.vessels.tank.Tank.pressurant_for_expulsion(), feedtwin.vessels.tank.Tank.rates(), feedtwin.session.network_trace.NetworkTrace.record(), and skip_chill().
|
static |
|
static |
Definition at line 1223 of file core.py.
Referenced by _settled().
| feedtwin.session.core.TankSim.state |
Definition at line 1240 of file core.py.
Referenced by _atmosphere_floor(), feedtwin.session.core.Session._burnout_check(), _chill(), _chill_target(), _collect(), _dewar_load(), feedtwin.session.core.Session._fire_notes(), _gas_temperature_of(), feedtwin.session.core.Session._integrate(), _ledger(), feedtwin.session.core.Session._loading(), feedtwin.session.core.Session._notes(), _one_step(), _pressurant_floor(), _settled(), _specific_energy_at(), feedtwin.session.core.Session._supply_press(), _wanted(), feedtwin.session.core.BottleSim.advance(), advance(), feedtwin.session.network_trace.NetworkTrace.append(), feedtwin.session.core.Session.command_state(), fill_line_flow(), outlet_pressure(), feedtwin.session.core.Session.prime(), feedtwin.session.network_trace.NetworkTrace.record(), engine.control.robust_ddp.controller.RobustDDPController.reset(), feedtwin.session.core.Session.signals(), skip_chill(), engine.control.robust_ddp.controller.RobustDDPController.step(), take_back(), test_robust_ddp_actuation.TestActuation.test_compute_actuation_binary(), test_robust_ddp_actuation.TestActuation.test_compute_actuation_clamping(), test_robust_ddp_actuation.TestActuation.test_compute_actuation_pwm(), test_robust_ddp_safety_filter.TestSafetyFilter.test_filter_action_clamping(), test_robust_ddp_safety_filter.TestSafetyFilter.test_filter_action_safe(), test_robust_ddp_safety_filter.TestSafetyFilter.test_filter_action_unsafe_mr(), test_robust_ddp_safety_filter.TestSafetyFilter.test_filter_action_unsafe_ullage(), and test_robust_ddp_safety_filter.TestSafetyFilter.test_find_best_safe_action().
|
static |
|
static |
|
static |