|
STAR
Cal STAR — firmware, DAQ server, and engine design
|
Public Member Functions | |
| None | __init__ (self, Model model, StateMachine machine, Binding binding, *, str state="Idle", Setup|None setup=None, Hookup|None hookup=None) |
| frozenset[str] | ground (self) |
| dict[str, float] | fire_loads (self) |
| list[str] | short_loads (self) |
| tuple[str,...] | vehicle_tanks (self) |
| dict[str, str] | builtin (self) |
| None | prime (self, *, float fill_fraction=0.95, float tank_psi=500.0, float copv_psi=0.0, str state="Ready", float hold_s=PAD_HOLD_S, Mapping[str, float]|None loads=None) |
| None | apply_thermal (self) |
| None | command_state (self, str state) |
| list[str] | operator_held (self) |
| None | set_valve (self, str drawing_id, bool is_open) |
| None | release (self, str drawing_id="") |
| list[str] | skip_chilldown (self, str tank_id="") |
| dict[str, float] | signals (self, float dt=0.0) |
| dict[str, float] | peek_signals (self, *, bool loaded_dome=False) |
| float | inventory (self) |
| None | reset_balance (self) |
| Sample | step (self, float dt) |
| bool | lit_this_state (self) |
Public Attributes | |
| id = uuid.uuid4().hex[:12] | |
| model = model | |
| machine = machine | |
| binding = binding | |
| hookup = hookup | |
| tuple | knobs |
| str | state = state if state in machine.states else machine.states[0] |
| gse_ignored = bool(model.meta.get("vehicle_only")) | |
| setup = setup or Setup() | |
| dict | forced = {} |
| str|None | tripped = None |
| Trip|None | trip = None |
| str|None | burnout = None |
| float | t = 0.0 |
| wall = time.monotonic() | |
| Deque[Sample] | history = deque(maxlen=HISTORY) |
| Deque[SolverRecord] | solver_log = deque(maxlen=HISTORY) |
| watcher = Watcher() | |
| list | assumptions = [] |
| dict | tanks = {} |
| dict | bottles = {} |
| operator_held | |
| ground | |
| dict | walls = {} |
| dict | wall_temperature = {} |
| dict | arriving_enthalpy = {} |
Protected Member Functions | |
| frozenset[str] | _find_drawn_fills (self) |
| list[PidNode] | _cut_dome_regulators (self) |
| dict[str, frozenset[str]] | _find_cut_dome_ports (self) |
| dict[str, DomeLine] | _find_cut_dome_lines (self) |
| None | _build_vessels (self) |
| float|None | _ullage_wall_T0 (self, str tank_id, TankSim sim) |
| float | _loader_supply (self, object loader) |
| Callable[[], GasFilm]|None | _film_estimator (self, Fluid gas, object node, CylindricalTank geometry) |
| dict[str, Any] | _tank_wall_defaults (self) |
| dict[str, Any] | _bottle_wall_defaults (self) |
| float | _gated_dome (self, DomeLine|None line, float live, Mapping[str, float] commanded) |
| float | _through_loader (self, DomeLoader loader, float psig_set) |
| float | _slew (self, str drawing_id, float target, float dt) |
| float | _travel_time (self, str drawing_id) |
| frozenset[str] | _through_outlets (self) |
| frozenset[str] | _dry_branches (self) |
| bool | _firing (self) |
| None | _rest_ground (self, Mapping[str, float] signals) |
| tuple[frozenset[str], frozenset[str]] | _unreachable_ground (self, frozenset[str] shut) |
| float | _coupling_timescale (self, Mapping[str, float]|None signals=None, float dt=0.0, bool press=True) |
| dict[str, float] | _regulator_slopes (self, frozenset[str] shut) |
| float | _press_path_timescale (self, TankSim sim, float capacitance, Mapping[str, float]|None signals, float dt=0.0) |
| dict[str, float] | _vessel_pressures (self) |
| dict[str, tuple[float, float]] | _ullage_storage (self, float dt, frozenset[str] isolated) |
| None | _close_outlet (self, TankSim sim, float dt, set[str] cut, dict[str, tuple[float, float]] out) |
| SteadyResult | _advance_once (self, Network net, Mapping[str, float] signals, float dt, int substeps=SUBSTEPS) |
| float | _dry_cut (self, Mapping[str, float] flows, float dt) |
| None | _note_solve (self, SteadyResult result) |
| frozenset[str] | _boundary_nodes (self) |
| tuple[float, float, float] | _ledger_totals (self) |
| None | _record_solver (self, int couplings) |
| dict[str, float] | _relief_signals (self, Network net, Mapping[str, float] signals, Mapping[str, float]|None pressures=None) |
| None | _accept (self, SteadyResult result) |
| SteadyResult | _solve (self, Network net, Mapping[str, float] signals, frozenset[str] isolate, Mapping[str, tuple[float, float]]|None storage) |
| Mapping[str, float] | _held (self, SteadyResult result) |
| SteadyResult | _close_chamber (self, Network net, Mapping[str, float] signals, frozenset[str] dry, SteadyResult result, Mapping[str, tuple[float, float]]|None storage=None) |
| None | _move_vessels (self, Mapping[str, float] flows, Mapping[str, float] pressures, float dt, int substeps=SUBSTEPS) |
| dict[str, str] | _find_fill_stops (self) |
| bool | _loading (self, TankSim sim) |
| None | _stop_full_loads (self) |
| tuple[float, float, float] | _supply_press (self, TankSim sim, float dt=0.0) |
| float|None | _arriving_liquid_T (self, TankSim sim, Mapping[str, float] flows) |
| frozenset[str] | _sealed (self, frozenset[str] isolated) |
| bool | _venting (self, str node, Mapping[str, float] flows) |
| float | _vent_fraction (self, str node, Mapping[str, float] flows) |
| None | _apply_vessel_pressures (self) |
| dict[str, str] | _find_fill_stubs (self) |
| list[str] | _leaking_notes (self) |
| tuple[float, float] | _split_at (self, str node, Mapping[str, float] flows) |
| tuple[float, float] | _outlet_split (self, TankSim sim, Mapping[str, float] flows, frozenset[str]|None through=None) |
| float | _net_into (self, str node, Mapping[str, float] flows) |
| Sample | _integrate (self, float dt) |
| float | _supply_to (self, TankSim sim, Mapping[str, float] pressures) |
| float | _pressurant_enthalpy (self, TankSim sim) |
| float | _bottle_inflow_enthalpy (self, BottleSim bottle) |
| BottleSim|None | _bottle_for (self, TankSim sim) |
| bool | _fills (self, TankSim sim) |
| None | _build_line_walls (self) |
| float | _off_the_dew_line (self, Fluid fluid, float pressure, float enthalpy, float landed, str node_id) |
| None | _propagate_temperatures (self, Mapping[str, float] pressures, Mapping[str, float] flows, float dt=0.0) |
| None | _chamber (self, Mapping[str, float] flows) |
| None | _burnout_check (self) |
| list[str] | _fire_notes (self) |
| None | _check_limits (self) |
| list[tuple[str, Any]] | _reliefs_on (self, str vessel) |
| list[str] | _notes (self) |
Protected Attributes | |
| dict | _positions = {} |
| dict | _dome_held = {} |
| dict | _dome_readings = {} |
| bool | _dome_primed = False |
| dict | _travel = {} |
| Sample|None | _shown = None |
| float|None | _lit_at = None |
| float | _state_since = 0.0 |
| dict | _tick = {} |
| frozenset[str]|None | _boundary = None |
| float | _crossed_in = 0.0 |
| float | _crossed_out = 0.0 |
| float|None | _inventory0 = None |
| tuple | _ledger0 = (0.0, 0.0, 0.0) |
| float | _guard_J0 = 0.0 |
| dict | _last_flows = {} |
| dict | _last_pressures = {} |
| dict | _guess = {} |
| float | _last_change = 0.0 |
| float | _last_dt = 1.0 |
| frozenset[str] | _last_isolated = frozenset() |
| tuple | _resting |
| dict[str, float]|None | _fire_loads = None |
| tuple[ | _resting_memo |
| tuple | _regulator_memo = (None, {}) |
| _chamber_guess = AMBIENT | |
| ChamberResult|None | _last_chamber = None |
| str | _chamber_node = "" |
| _design_chamber = AMBIENT | |
| dict | _trapped = {} |
| dict[str, str] | _fill_stubs = self._find_fill_stubs() |
| frozenset[str] | _fill_hoses |
| frozenset[str] | _drawn_fill = self._find_drawn_fills() |
| tuple | _dome_ports |
| tuple | _cut_dome_lines |
| frozenset[str] | _liquid_fed |
| dict | _fill_lines = {} |
| dict[str, str] | _fill_stops = self._find_fill_stops() |
| set[str] | _fill_stopped = set() |
| dict | _sealed_cache = {} |
| dict | _fill_crew = {} |
| list | _reliefs |
| dict | _relief_open = {} |
| dict | _relief_lift = {} |
A stand, live. Built once, ticked forever. The state machine commands valves, the valves decide what is connected, the network decides the flows and the vessels decide what that does to their contents. Nothing here scripts a pressure curve; every number on screen is the consequence of the previous tick.
| None feedtwin.session.core.Session.__init__ | ( | self, | |
| Model | model, | ||
| StateMachine | machine, | ||
| Binding | binding, | ||
| * | , | ||
| str | state = "Idle", | ||
| Setup | None | setup = None, | ||
| Hookup | None | hookup = None ) |
|
protected |
Keep a converged solve as the next one's starting point.
Definition at line 4239 of file core.py.
References _guess, _last_flows, and _last_pressures.
Referenced by _advance_once(), and _close_chamber().
|
protected |
One coupling step: solve the network, then move the vessels.
Definition at line 4008 of file core.py.
References _accept(), _advance_once(), _apply_vessel_pressures(), _boundary_nodes(), _close_chamber(), _crossed_in, _crossed_out, _dry_branches(), _dry_cut(), _fill_hoses, _guess, _held(), _last_flows, _last_isolated, _move_vessels(), _note_solve(), _propagate_temperatures(), _relief_open, _relief_signals(), _reliefs, _resting, _solve(), _ullage_storage(), anonymous_namespace{idle_e2e.cpp}::World.setup, and setup.
Referenced by _advance_once(), and _integrate().
|
protected |
Definition at line 4859 of file core.py.
References _fill_stubs, _through_outlets(), feedtwin.session.burn.Probes.bottles, bottles, model, feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, and tanks.
Referenced by _advance_once().
|
protected |
Mass-weighted temperature of what arrives at a tank's outlet [K].
Definition at line 4743 of file core.py.
References model.
Referenced by _move_vessels().
The bottle feeding this ullage, if one is reachable. Matched on species rather than walked: a stand has one pressurant, and a walk would have to cross the regulator's dome branch to find it.
Definition at line 5328 of file core.py.
References feedtwin.session.burn.Probes.bottles, bottles, anonymous_namespace{idle_e2e.cpp}::World.ground, and ground.
Referenced by _pressurant_enthalpy().
|
protected |
Specific enthalpy of gas the drawing delivers into a bottle [J/kg]: the walk's arrival at its node, else cart gas at the fill temperature.
Definition at line 5316 of file core.py.
References arriving_enthalpy, max, anonymous_namespace{idle_e2e.cpp}::World.setup, and setup.
Referenced by _move_vessels().
|
protected |
Definition at line 3104 of file core.py.
References anonymous_namespace{idle_e2e.cpp}::World.setup, and setup.
Referenced by _build_vessels().
|
protected |
Definition at line 4134 of file core.py.
References _boundary, feedtwin.session.burn.Probes.bottles, bottles, model, feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, and tanks.
Referenced by _advance_once(), and _leaking_notes().
|
protected |
One lumped wall per line, started at the temperature its line holds. This is the whole of the "soak" question, answered without a soak model. A wall left to sit converges on the temperature of the fluid inside it, so that is where it starts -- and it falls out per line for free: * a line full of liquid oxygen has been sitting near 90 K, so its fittings are cold and have little heat to give; * the ullage side above that tank holds cold vapour, cooler than the room and nowhere near the liquid; * a pressurant line that has only ever seen ambient gas is at ambient, and is the one with real heat in it. Three very different wall temperatures, none of them assumed. Tracking how a stand drifts while it sits would need an ambient boundary, an insulation state and an hours-long clock on every line, and would land in the same place this does.
|
protected |
Turn the drawing's tanks and bottles into integrable vessels. Tanks start **empty and at atmosphere** whatever the drawing's pressure field says. That field is a design pressure, not a starting condition, and starting a simulator at the answer is the thing that made the last one useless.
Definition at line 2719 of file core.py.
References feedtwin.session.core._bottle_geometry(), _bottle_wall_defaults(), _film_estimator(), feedtwin.session.core._not_a_liquid_tank(), feedtwin.session.core._skin_conductance(), feedtwin.session.core._tank_geometry(), _tank_wall_defaults(), feedtwin.session.core._trip_limit(), feedtwin.session.core._vessel_wall(), assumptions, feedtwin.session.burn.Probes.bottles, bottles, anonymous_namespace{idle_e2e.cpp}::World.ground, ground, model, anonymous_namespace{idle_e2e.cpp}::World.setup, setup, feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, and tanks.
|
protected |
Burnout: a tank ran dry during Fire, so the sequence goes to Vent. The stand's fire is timed and ends in Vent; the twin's ends when the propellant does. Without this the mains stayed open on empty tanks and both sat at lockup with the regulator holding them there, which the operator rightly read as "nothing vented". Vent is what the table says it is: both tank vents, both press valves, the manifold vent.
Definition at line 5710 of file core.py.
References _state_since, burnout, command_state(), lit_this_state(), machine, model, anonymous_namespace{idle_e2e.cpp}::World.setup, setup, anonymous_namespace{idle_e2e.cpp}::Beat.state, anonymous_namespace{idle_e2e.cpp}::World.state, battery_t.state, feedtwin.session.core.BottleSim.state, state, feedtwin.session.core.TankSim.state, gnss_core_t.state, gnss_frame_parser_t.state, SensorHotfire::CoreState.state, Valve.state, world_t.state, anonymous_namespace{idle_e2e.cpp}::Beat.t, anonymous_namespace{idle_e2e.cpp}::World::Ground.t, feedtwin.model.component.EvalContext.t, feedtwin.session.burn.BurnTrace.t, t, gui.App.t, lc_calibration_gui.LCPlotWindow.t, rec_t.t, feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, tanks, and vehicle_tanks().
Referenced by _integrate().
|
protected |
The chamber boundary when there is no engine model on the drawing.
Definition at line 5658 of file core.py.
References _chamber_node, _design_chamber, max, min, model, feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, tanks, and vehicle_tanks().
Referenced by _close_chamber().
|
protected |
Trip the stand if a vessel is over the pressure the drawing rates it for. A hand-loaded regulator turned too far, a shut LOX tank left to boil, a fill with the vent closed: the model would happily carry a tank to the propellant's critical pressure and beyond. A real one lets go. Above its MAWP the stand stops, says which vessel and how far, and asks to be reset -- the operator learns what they did, and nothing pretends to run on past a failure.
Definition at line 5800 of file core.py.
References _reliefs_on(), feedtwin.session.burn.Probes.bottles, bottles, max, model, anonymous_namespace{idle_e2e.cpp}::Beat.t, anonymous_namespace{idle_e2e.cpp}::World::Ground.t, feedtwin.model.component.EvalContext.t, feedtwin.session.burn.BurnTrace.t, t, gui.App.t, lc_calibration_gui.LCPlotWindow.t, rec_t.t, feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, tanks, trip, feedtwin.session.burn.BurnEnd.tripped, and tripped.
Referenced by _integrate().
|
protected |
Find the chamber pressure the network and the engine agree on. With the chamber pinned at ``p`` the network delivers some flow; the engine turns that flow into a chamber pressure ``g(p)`` through c* and the throat. The two agree where ``g(p) = p``. ``g`` falls as ``p`` rises (a higher chamber takes injector drop away), it is above ambient at ambient whenever propellant is arriving, and it is ambient at the feed pressure where nothing flows -- so a root is bracketed and regula falsi with a bisection guard finds it in a handful of solves. A step where the previous answer still holds costs nothing extra: the first solve is the one already made. Sets ``_chamber_guess``, the chamber node, and ``_last_chamber``.
Definition at line 4338 of file core.py.
References _accept(), _chamber(), _chamber_guess, _last_chamber, _last_flows, _note_solve(), _solve(), _tick, max, min, model, anonymous_namespace{idle_e2e.cpp}::World.setup, setup, feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, and tanks.
Referenced by _advance_once().
|
protected |
Close a shut-in tank's outlet over the step, as its ullage is closed. With the vent and the press line shut the ullage holds a fixed mass, so every gram of liquid that leaves expands it: the outlet is as stiff as that ullage. Held at its start-of-step pressure it is an explicit coupling -- a full LE4 fuel tank drained through a quarter-psi head swung its drain 30 g/s each way, step after step, and leaked 2 g/s where it should have stopped. Closed here (``solve_steady(storage=)``): where the outlet lands with no liquid exchanged, and how far one probe's worth of draining moves it -- both by trial steps on a copy. Only for a tank with liquid in it and a live line at its outlet; a tank whose outlet is a junction (:meth:`_through_outlets`) has none of its own.
Definition at line 3953 of file core.py.
References _through_outlets(), max, and model.
Referenced by _ullage_storage().
|
protected |
Shortest ullage RC time constant on the stand [s], or 0. ``C = V rho / p`` is the isothermal gas capacitance of an ullage -- how much mass it takes to raise its pressure by a pascal. Two resistances are paired with it, and the shorter product is what the coupling step has to resolve. The regulator's slope, ``flow_droop / rated_flow``: how many pascals its outlet gives up per kg/s drawn. That is the regulator-ullage loop. And the ullage's own press path (:meth:`_press_path_timescale`): what the flow into the tank does when the *tank* moves, with the outlet node next door held. Two tanks on one press manifold trade gas through nothing but their solenoids, and on helium that is a few milliseconds where the regulator's is tens. Stepped past it, each solve sent gas the wrong way through a solenoid for a whole coupling step: the tank fell 15-30 psi in a quarter of a hundredth of a second, the other dumped into it, and every LE4 helium burn plotted a 0.5-0.8 s sawtooth that cost 170 N of mean thrust (2026-10-05).
Definition at line 3622 of file core.py.
References _dry_branches(), _press_path_timescale(), _regulator_slopes(), _resting, min, model, feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, and tanks.
Referenced by _integrate().
|
protected |
The dome-loaded regulators whose loader is not on the drawing: it was on the cart and went with it (:attr:`Setup.ignore_gse`).
Definition at line 2598 of file core.py.
References model.
Referenced by _find_cut_dome_lines(), and _find_cut_dome_ports().
|
protected |
Feed branches leaving a tank with nothing left in it.
Definition at line 3499 of file core.py.
References _fill_lines, _loading(), _through_outlets(), model, feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, and tanks.
Referenced by _advance_once(), _coupling_timescale(), _press_path_timescale(), and _rest_ground().
|
protected |
How much of a ``dt`` step the tanks can feed these ``flows`` [s]. ``dt`` unless a tank still feeding would be drained before the step ends; then the time at which the first of them is. Only a tank above :data:`DRY_MASS` counts: one below it is already isolated (:meth:`_dry_branches`), so the remainder of a cut step cannot cut again on the same tank.
Definition at line 4101 of file core.py.
References _liquid_fed, _split_at(), feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, and tanks.
Referenced by _advance_once().
|
protected |
Whether the current state is filling this tank. Never a cart's tank: that is where a load comes from, pre-loaded. Matched on the state's name against the tank's fluid, because fill comes from a tanker that is not on the drawing -- see FILL_RATE. The rule is :func:`~feedtwin.session.statemachine.fills`, which an edited table is checked against.
Definition at line 5344 of file core.py.
Referenced by _integrate().
|
protected |
A thunk for the still-gas film of one vessel, or None when the setup says to keep the per-litre default.
Definition at line 3072 of file core.py.
References anonymous_namespace{idle_e2e.cpp}::World.setup, and setup.
Referenced by _build_vessels().
|
protected |
Each cut dome line (:meth:`_find_cut_dome_ports`) with a valve drawn on the vehicle's half of it, as a :class:`DomeLine` whose loader is the capped disconnect the cart's dome supply came in through. The dome line is loading gas off the cart, and like the cart's vents it stays plugged into the rocket while the stand is on it: rocket only, the dome comes in at the knob through that disconnect, and the rocket's own dome valve decides whether it reaches the regulator. :meth:`_gated_dome` walks it as it walks a drawn line, so a valve no state-table row drives passes and the dome follows the knob exactly as before; one a row drives loads the dome only in the states that open it, and holds what was shut in otherwise. Walked from the ``dome`` handle through junctions, valves and instruments to one disconnect; a line that reaches none, or more than one, is left as it was.
Definition at line 2652 of file core.py.
References _cut_dome_regulators(), and model.
|
protected |
The network nodes a dome-loaded regulator's dome line reaches, for each one with no loader left on the drawing: its loader was on the cart and went with it (:attr:`Setup.ignore_gse`). The line is no plumbing, so the solve leaves it at atmosphere; its transducer reads the dome the knob sets. Walked from the ``dome`` handle through junctions and instruments, stopping at any valve, regulator, disconnect or vessel.
Definition at line 2611 of file core.py.
References _cut_dome_regulators(), and model.
|
protected |
The vessels the drawing fills (:func:`drawn_fills`), each said: its built-in fill steps aside.
Definition at line 2575 of file core.py.
References assumptions, feedtwin.session.core.drawn_fills(), and model.
|
protected |
For each tank a cart tank loads: the first valve on the transfer line, from the cart's side. Hand or actuated; none if the line has no valve.
Definition at line 4588 of file core.py.
References _fill_lines, path.append(), and model.
|
protected |
Free boundary node of each fill valve -> the vessel node it feeds.
Definition at line 4879 of file core.py.
References binding, feedtwin.session.burn.Probes.bottles, bottles, model, feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, and tanks.
|
protected |
What Fire is actually doing, and what an abort's row leaves open. Fire with nothing lit is a cold flow: tanks too low to start the engine push propellant through it at a few psi and no thrust, and the console called that "Burning" for as long as anyone let it (D-10). An abort the stand's table writes with a main open keeps feeding the engine; the twin does what the DAQ would (NEEDS-REPAIR.md), and says so where the operator is looking, with where to fix it (D-18).
Definition at line 5761 of file core.py.
References _state_since, lit_this_state(), machine, model, anonymous_namespace{idle_e2e.cpp}::Beat.state, anonymous_namespace{idle_e2e.cpp}::World.state, battery_t.state, feedtwin.session.core.BottleSim.state, state, feedtwin.session.core.TankSim.state, gnss_core_t.state, gnss_frame_parser_t.state, SensorHotfire::CoreState.state, Valve.state, world_t.state, anonymous_namespace{idle_e2e.cpp}::Beat.t, anonymous_namespace{idle_e2e.cpp}::World::Ground.t, feedtwin.model.component.EvalContext.t, feedtwin.session.burn.BurnTrace.t, t, gui.App.t, lc_calibration_gui.LCPlotWindow.t, rec_t.t, feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, tanks, and vehicle_tanks().
Referenced by _notes().
|
protected |
Propellant reached the engine on the last solve.
Definition at line 3529 of file core.py.
References _last_flows, and model.
Referenced by _leaking_notes(), and _rest_ground().
|
protected |
The dome a gated dome line gives: its loader's outlet while the line is open between them, atmosphere once an open vent reaches the port side, and otherwise what was shut in [Pa abs]. Walked from the dome port each tick, through what is open. A valve no actuator drives passes (nothing on the stand shuts it); a vent valve no actuator drives, and a hand valve nobody has opened, rest shut.
Definition at line 3356 of file core.py.
References _dome_held, _dome_primed, _dome_readings, forced, and model.
Referenced by signals().
|
protected |
The node pressures a step acts on and shows. The solve's own when it converged. A failed solve's iterate is not a pressure field either, so every node it was solving for stays where the last converged solve left it; only the boundaries -- vessels, atmosphere, the chamber -- are taken as they stand, because the session set those itself. Before any solve has converged there is nothing to hold and the iterate is all there is.
Definition at line 4318 of file core.py.
References _last_pressures, and model.
Referenced by _advance_once(), and _integrate().
|
protected |
Advance the stand by ``dt`` seconds and return where it is.
Definition at line 5043 of file core.py.
References _advance_once(), _burnout_check(), _check_limits(), _coupling_timescale(), _dome_readings, _drawn_fill, _fills(), _held(), _last_chamber, _last_change, _last_dt, _last_flows, _lit_at, _notes(), _record_solver(), _relief_lift, _rest_ground(), _resting, _split_at(), _stop_full_loads(), _tick, _trapped, _vent_fraction(), _vessel_pressures(), feedtwin.session.burn.Probes.bottles, bottles, fire_loads(), anonymous_namespace{idle_e2e.cpp}::World.ground, ground, history, machine, max, min, model, anonymous_namespace{idle_e2e.cpp}::World.setup, setup, feedtwin.comps.base.FlowConditions.signals, feedtwin.model.component.EvalContext.signals, feedtwin.session.core.Sample.signals, signals(), anonymous_namespace{idle_e2e.cpp}::Beat.state, anonymous_namespace{idle_e2e.cpp}::World.state, battery_t.state, feedtwin.session.core.BottleSim.state, state, feedtwin.session.core.TankSim.state, gnss_core_t.state, gnss_frame_parser_t.state, SensorHotfire::CoreState.state, Valve.state, world_t.state, anonymous_namespace{idle_e2e.cpp}::Beat.t, anonymous_namespace{idle_e2e.cpp}::World::Ground.t, feedtwin.model.component.EvalContext.t, feedtwin.session.burn.BurnTrace.t, t, gui.App.t, lc_calibration_gui.LCPlotWindow.t, rec_t.t, feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, and tanks.
Referenced by engine.layerx.flight.InlineAscent.advance(), and step().
|
protected |
Where a vehicle tank's propellant is going, when it is not the engine. On LE4 the cart's FD-ROT-G -- a dump nothing in the state table commands, resting open as drawn -- emptied the flight fuel tank through its fill line in about ten seconds after T-0, and nothing on screen said where the fuel went (2026-10-09). This names the way out: each branch carrying that propellant across the stand's boundary, and whether the state table drives it. Read off the last solve; changes nothing.
Definition at line 4922 of file core.py.
References _boundary_nodes(), _firing(), _last_flows, _split_at(), binding, anonymous_namespace{idle_e2e.cpp}::World.ground, ground, model, feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, and tanks.
Referenced by _notes().
|
protected |
``(added, removed, guards)`` the vessels booked themselves [kg].
Definition at line 4150 of file core.py.
References feedtwin.session.burn.Probes.bottles, bottles, feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, and tanks.
Referenced by _record_solver(), and reset_balance().
|
protected |
Pressure feeding a dome control regulator [Pa]. The bottle it hangs off, read from state rather than from the last solve: the dome has to be known *before* the network is solved, and a stale node pressure from the previous tick would put the dome one step behind the supply it is supposed to track.
Definition at line 3058 of file core.py.
References feedtwin.session.burn.Probes.bottles, bottles, anonymous_namespace{idle_e2e.cpp}::World.ground, and ground.
Referenced by _through_loader().
|
protected |
The stand is in this tank's fill state ("Fuel Fill", "Ox Fill").
Definition at line 4643 of file core.py.
References anonymous_namespace{idle_e2e.cpp}::Beat.state, anonymous_namespace{idle_e2e.cpp}::World.state, battery_t.state, feedtwin.session.core.BottleSim.state, state, feedtwin.session.core.TankSim.state, gnss_core_t.state, gnss_frame_parser_t.state, SensorHotfire::CoreState.state, Valve.state, and world_t.state.
Referenced by _dry_branches(), _stop_full_loads(), and _through_outlets().
|
protected |
Integrate every vessel over ``dt`` with the flows it is given. The ground at rest is left where it is (:attr:`Setup.ground_rests`): what :meth:`_rest_ground` took out of the solve, and any cart vessel these flows do not touch and no built-in press is acting on.
Definition at line 4430 of file core.py.
References _arriving_liquid_T(), _bottle_inflow_enthalpy(), _drawn_fill, _last_isolated, _liquid_fed, _net_into(), _outlet_split(), _pressurant_enthalpy(), _resting, _sealed(), _split_at(), _supply_press(), _supply_to(), _through_outlets(), _vent_fraction(), feedtwin.session.burn.Probes.bottles, bottles, anonymous_namespace{idle_e2e.cpp}::World.ground, ground, min, model, anonymous_namespace{idle_e2e.cpp}::World.setup, setup, feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, and tanks.
Referenced by _advance_once().
|
protected |
|
protected |
Count one network solve into this tick's solver record.
Definition at line 4122 of file core.py.
Referenced by _advance_once(), and _close_chamber().
|
protected |
Definition at line 5891 of file core.py.
References _drawn_fill, _fire_notes(), _leaking_notes(), _reliefs_on(), feedtwin.session.burn.Probes.bottles, bottles, burnout, anonymous_namespace{idle_e2e.cpp}::World.ground, ground, machine, max, anonymous_namespace{idle_e2e.cpp}::World.setup, setup, anonymous_namespace{idle_e2e.cpp}::Beat.state, anonymous_namespace{idle_e2e.cpp}::World.state, battery_t.state, feedtwin.session.core.BottleSim.state, state, feedtwin.session.core.TankSim.state, gnss_core_t.state, gnss_frame_parser_t.state, SensorHotfire::CoreState.state, Valve.state, world_t.state, feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, and tanks.
Referenced by _integrate().
|
protected |
A gas node the walk landed inside the two-phase dome, held as saturated vapour :data:`_DEW_MARGIN_K` above its dew point. Venting cold pressurant expands it down its own saturation line: GN2 off a chilled LOX tank, throttled to an atmosphere, landed at 77.87 K and 107.6 kPa -- nitrogen's boiling point there -- and every solve after it failed on its first property call (the state is on the line, so liquid or vapour is not said). The lines carry one phase, so a mostly-vapour landing (quality at least a half) is taken as the vapour it nearly is; the fog it would really carry is not modelled, and the notes say so once. A mostly-liquid landing -- a flashing liquid -- is left where it was.
Definition at line 5424 of file core.py.
References assumptions, and max.
Referenced by _propagate_temperatures().
|
protected |
Liquid arriving at and leaving a tank's outlet [kg/s]: nothing for a dry tank whose outlet is a junction (:meth:`_through_outlets`), whose flows pass the tank by.
Definition at line 4996 of file core.py.
References _split_at(), and _through_outlets().
Referenced by _move_vessels(), _press_path_timescale(), and _ullage_storage().
|
protected |
``C / G`` for one ullage while its tank is delivering liquid [s]. ``G`` is the ullage's admittance: the sum over the gas branches on it of ``1 / (d dp / d mdot)``, each slope taken at the flow the last solve put through it -- or at the flow the ullage needs to replace the liquid leaving it, if that is more. Counting only the branch on the tank and not what lies beyond it overstates ``G``, so it errs toward more steps. Only while liquid is leaving. A tank at rest has no drain to outrun its press path, and at zero flow a quadratic loss has zero slope: the constant goes to zero and would spend the step limit on a pad hold that a few grams of slosh cannot disturb. And only while the tank rides its supply -- within ``supply_band`` of the node feeding it, the band in which :meth:`TankSim.advance` clamps the inflow. That is where a step's drain carries the tank across its supply and the next solve sends its gas back out. A tank sitting clearly under its supply cannot be carried across, and gets nothing from the finer steps: the shipped GN2 stand burns 6-8 psi under its manifold and traced identically either way, at twice the cost. And only while the drain is enough to matter: over the tick, more than :data:`PRESS_PATH_DRAIN_FRACTION` of that band. Below it the drain cannot carry the tank across its supply, and what is left is a nearly empty tank at an abort, with a trickle out and a trickle in -- whose zero-flow slope asked for 0.3 ms steps and stalled the panel. Infinity when there is nothing to measure.
Definition at line 3732 of file core.py.
References _dry_branches(), _guess, _last_flows, _outlet_split(), max, model, anonymous_namespace{idle_e2e.cpp}::World.setup, and setup.
Referenced by _coupling_timescale().
|
protected |
Enthalpy of the gas arriving at this ullage [J/kg]. **A regulator is a throttle, so enthalpy is what carries across it**, not temperature and not entropy. The gas that reaches the tank has the specific enthalpy it had in the bottle; its *temperature* is then whatever that enthalpy corresponds to at the delivery pressure, and that is a real-gas question with an answer that reverses between fluids. Nitrogen at room temperature sits above its Joule-Thomson inversion curve, so throttling from 4500 psi to 500 cools it about thirty kelvin. Helium's inversion temperature is around forty-five kelvin, far below anything on a pad, so the same expansion *warms* it about seventeen. A tank being pressed with helium therefore receives gas nearly fifty kelvin warmer than the same tank on nitrogen -- which is most of why the two behave so differently out of a small bottle. Assuming a fixed delivery temperature, as this used to, erases that entirely: both gases arrive at 293 K and the only thing left telling them apart is molar mass.
Definition at line 5259 of file core.py.
References _bottle_for(), arriving_enthalpy, anonymous_namespace{idle_e2e.cpp}::World.setup, and setup.
Referenced by _move_vessels(), and _ullage_storage().
|
protected |
Carry enthalpy along the flow path, so every node has a real temperature. Node temperatures were set once at build time and never written again. The vessel models track cooling carefully -- a LOX ullage at 268.7 K where the drawing said 293.15 -- and the network then metered gas out of that node at the temperature it was born with. A 24.5 K error is about 9% on density and 4.5% on the flow through it, and it grew through a burn, so it was a drifting error rather than a constant one. **Enthalpy, not temperature, is what propagates.** Every component here is adiabatic, and an adiabatic component with no shaft work conserves enthalpy -- which is exactly the argument this codebase already makes for the regulator, and the reason nitrogen cools ~30 K through it while helium warms ~17 K. Carrying ``h`` and re-solving ``T(h, p)`` at each node's own pressure therefore gets Joule-Thomson right at *every* throttle for free, rather than special-casing the one we thought about. What it does not model: heat into the line walls, and viscous heating. Both are small against a five-second burn and neither is free to add -- a wall needs its own thermal state per line. Lagged by one tick, deliberately. This runs *after* the solve and annotates the network, so it cannot perturb the Newton iteration; the next tick's solve picks up the new temperatures. Same arrangement as the chamber boundary, and for the same reason.
Definition at line 5464 of file core.py.
References _off_the_dew_line(), arriving_enthalpy, feedtwin.session.burn.Probes.bottles, bottles, max, model, anonymous_namespace{idle_e2e.cpp}::World.setup, setup, feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, tanks, wall_temperature, and walls.
Referenced by _advance_once().
|
protected |
Close this tick's solver record.
Definition at line 4168 of file core.py.
References _crossed_in, _crossed_out, _inventory0, _ledger0, _ledger_totals(), _tick, inventory(), reset_balance(), solver_log, anonymous_namespace{idle_e2e.cpp}::Beat.t, anonymous_namespace{idle_e2e.cpp}::World::Ground.t, feedtwin.model.component.EvalContext.t, feedtwin.session.burn.BurnTrace.t, t, gui.App.t, lc_calibration_gui.LCPlotWindow.t, rec_t.t, feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, tanks, and watcher.
Referenced by _integrate().
|
protected |
Each ullage's stiffest regulator slope, ``flow_droop / rated_flow`` [Pa/(kg/s)], over the regulators it is joined to. Walked from the ullage across every branch not ``shut``, never on through another boundary (a vessel, the sky). A regulator the tank has no open path to is no loop with it: every regulator on the stand used to be paired with every ullage, so a LOX tank topped in Ox Fill, its press valve shut, was stepped at the cart's fuel regulator's time constant -- three solves every 20 ms for a loop that did not exist. Remembered per shut set and boundaries, as ``Network.dead_ends`` is.
Definition at line 3674 of file core.py.
References _regulator_memo, min, model, feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, and tanks.
Referenced by _coupling_timescale().
|
protected |
Each relief valve's lift for this coupling step, as signals. From the pressure across it: ``pressures`` (a solve made at this step's vessel pressures) when given; otherwise a vessel boundary's own pressure where the valve's end is one, and the last converged solve's value at any other node. A node never yet solved leaves the valve where it was. See :mod:`feedtwin.comps.relief`.
Definition at line 4203 of file core.py.
References _guess, _relief_lift, _relief_open, and _reliefs.
Referenced by _advance_once().
|
protected |
The relief branches drawn on ``vessel``'s gas side: reached from its gas node without crossing a regulator, another vessel or another relief. A COPV's relief does not protect the tanks behind its regulator, nor one tank's relief the tank across the press manifold.
Definition at line 5851 of file core.py.
References _reliefs, feedtwin.session.burn.Probes.bottles, bottles, model, feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, and tanks.
Referenced by _check_limits(), and _notes().
|
protected |
Decide which ground support rests this step (``self._resting``). Nothing rests here unless the engine is burning, the drawing has ground support, and :attr:`Setup.ground_rests` is on. (A cart vessel with nothing flowing rests at any time: :meth:`_move_vessels`.)
Definition at line 3537 of file core.py.
References _dry_branches(), _firing(), _resting, _resting_memo, _unreachable_ground(), anonymous_namespace{idle_e2e.cpp}::World.ground, ground, model, anonymous_namespace{idle_e2e.cpp}::World.setup, and setup.
Referenced by _integrate().
|
protected |
Tanks whose ullage has no open gas path to the air. Walked from the ullage through every branch the solve did not take out (``isolated``: shut valves, dry outlets) to a fixed-pressure boundary that is not a vessel -- a vent, an open-ended valve. A vessel stops the walk: another tank or bottle is not the air, and the liquid below an ullage is not a gas path. With the vent shut and the press line closed, a tank is sealed (:attr:`TankSim.sealed`). Remembered per shut set.
Definition at line 4761 of file core.py.
References _sealed_cache, feedtwin.session.burn.Probes.bottles, bottles, model, feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, and tanks.
Referenced by _move_vessels().
|
protected |
Move one actuator toward ``target`` at its own travel rate.
Definition at line 3437 of file core.py.
References _positions, and _travel_time().
Referenced by signals().
|
protected |
The network at this coupling step, warm-started from the last answer. A solve with the ullages closed (``storage``) that fails is tried once more, from where the same network lands with them held: that solve is easy, and it puts Newton beside the answer. A failed solve holds the stand (:meth:`_held`), so the next step asks the same question and fails the same way, for good. A Fire from unpressed tanks did exactly that -- frozen with the chamber at 0 psig, where 384 iterations of the same solve converged and 9 + 4 by this route. Only a step that failed takes it, so every step that converges is the step it was.
Definition at line 4259 of file core.py.
References _guess, anonymous_namespace{idle_e2e.cpp}::World.setup, and setup.
Referenced by _advance_once(), and _close_chamber().
|
protected |
Mass arriving at and leaving a node [kg/s], kept apart. A tank being filled has pressurant coming in one port and vent gas going out another at the same time. Netting them loses the energy difference, and the sign of the net says nothing about either.
Definition at line 4973 of file core.py.
References model.
Referenced by _dry_cut(), _integrate(), _leaking_notes(), _move_vessels(), _net_into(), _outlet_split(), and _venting().
|
protected |
The crew's hand on a drawn load's transfer valve.
Shut until the tank's fill state ("Fuel Fill") is selected, opened for
the load, shut again once the tank holds it -- as the built-in load
stops at its full fraction. A transfer valve left at rest is open (it is
plumbed both sides), and a cart tank above the flight tank then siphons
into it before anyone has started the fill. Acts only when what the
crew would do changes, so a hand on the P&ID in between is kept.
Definition at line 4650 of file core.py.
References _fill_crew, _fill_stopped, _fill_stops, _loading(), assumptions, fire_loads(), forced, model, anonymous_namespace{idle_e2e.cpp}::World.setup, setup, feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, and tanks.
Referenced by _integrate().
|
protected |
The cart's press on a ground supply tank whose press line is not
drawn: ``(rate [kg/s], target [Pa], arriving enthalpy [J/kg])``.
A fuel transfer tank is pressed to the pressure its drawing gives while
the table holds its press actuator ("Fuel Fill Press") open. When a
valve on the drawing is bound to that actuator, the network presses it
and this is zero; so is it for every tank that is not the cart's.
Definition at line 4685 of file core.py.
References assumptions, binding, machine, max, model, anonymous_namespace{idle_e2e.cpp}::World.setup, setup, anonymous_namespace{idle_e2e.cpp}::Beat.state, anonymous_namespace{idle_e2e.cpp}::World.state, battery_t.state, feedtwin.session.core.BottleSim.state, state, feedtwin.session.core.TankSim.state, gnss_core_t.state, gnss_frame_parser_t.state, SensorHotfire::CoreState.state, Valve.state, and world_t.state.
Referenced by _move_vessels().
|
protected |
Pressure of whatever is feeding this ullage [Pa], or zero. The highest upstream node across a branch carrying gas *into* the ullage. Zero when nothing is, which leaves the vessel unclamped.
Definition at line 5243 of file core.py.
Referenced by _move_vessels().
|
protected |
Definition at line 3096 of file core.py.
References anonymous_namespace{idle_e2e.cpp}::World.setup, and setup.
Referenced by _build_vessels().
|
protected |
The dome a control regulator set to ``psig_set`` gives, from its supply now [Pa].
Definition at line 3423 of file core.py.
References _loader_supply(), and model.
Referenced by signals().
|
protected |
Dry tanks whose outlet other lines pass through, by tank id. An unsized tee on a tank's outlet line is joined into the outlet node (an unsized line is a direct connection), so on LE4 (6) the cart's transfer tank outlet *is* the tee between the fill line and the dump. Cutting every branch on a dry tank's outlet (:meth:`_dry_branches`) cut the fill line from the dump with it: Eth-Tank sat at 45 psig with the dump open and nothing solved. A dry tank's outlet with two or more lines on it -- and not being loaded through them -- is a junction instead: no pressure of its own (:meth:`_apply_vessel_pressures`), nothing taken from or given to the empty tank, flow passing between the lines.
Definition at line 3471 of file core.py.
References _loading(), model, feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, and tanks.
Referenced by _apply_vessel_pressures(), _close_outlet(), _dry_branches(), _move_vessels(), and _outlet_split().
|
protected |
|
protected |
Each ullage's closure over a ``dt`` coupling step, for the solve.
``{ullage node: (C / dt, reference)}`` (``solve_steady(storage=...)``):
where the vessel lands with no gas exchanged -- liquid still leaving at
the last solve's rate, the ullage collapsing, a load still pouring --
and how many kg/s over the step it takes to move it a pascal from
there. Both read off the vessel itself, by trial steps on a copy, so
whatever it models (charge heating, collapse, vapour) is in the slope
the network sees.
Without this the solve holds each tank at its start-of-step pressure,
an explicit coupling of a tiny capacitance behind a huge conductance.
LE4's 0.41 L ullages behind Cv 4 press solenoids flip-flopped through
their shared manifold every coupling step: one tank 5 psi high dumping
40 g/s, the other taking 100 g/s and refusing nearly all of it at its
supply clip, the regulator drooping at a phantom 60 g/s and both tanks
parked 25 psi under lockup for as long as the valves stayed open.
The slope taken is the stiffer of gas in (at the arriving enthalpy)
and gas out: over-stating the vessel's stiffness only damps the
closure, under-stating it hands back some of the explicit coupling.
A tank cut off by shut valves gets none and stays a fixed boundary.
Except an ullage draining to the sky (:meth:`_venting`), which is
closed on its gas-out slope alone. There the flow is one way and
steady, so the slope is not a damping: the node lands at
``reference - q dt / slope`` while the vessel lands where its own
slope puts it, and the stiffer one opens a gap between them that
grows with the step. Over boiling LOX the two differ eightfold --
warm gas arriving compresses the ullage, gas leaving is replaced by
flash boil-off -- and a topped tank on its vent sat 4 psi above the
node its vent flowed from, at 7.3 psig where finer coupling found
3.4. A vent ends at a fixed pressure, so there is no second vessel
across it to flip-flop with.
Definition at line 3859 of file core.py.
References _close_outlet(), _last_flows, _liquid_fed, _outlet_split(), _pressurant_enthalpy(), _venting(), max, model, feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, and tanks.
Referenced by _advance_once().
|
protected |
The upper-wall T-0 temperature the setup asks of this tank [K], or None for the previous behaviour (the pressurant's temperature).
Definition at line 3047 of file core.py.
References anonymous_namespace{idle_e2e.cpp}::World.setup, and setup.
Referenced by prime().
|
protected |
Ground branches and vessels with no open path to the vehicle. Walked from the vehicle's vessels and the engine across every branch not ``shut``. A tank is one place, so arriving at either of its nodes reaches both; any other fixed node -- atmosphere -- ends the walk, or every vent would join the cart to the vehicle through the sky.
Definition at line 3556 of file core.py.
References feedtwin.session.burn.Probes.bottles, bottles, anonymous_namespace{idle_e2e.cpp}::World.ground, ground, model, feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, and tanks.
Referenced by _rest_ground().
|
protected |
Share of the gas leaving ``node`` that ends at a vent, 0..1. Follow the flow out of the node through the network, splitting at each junction in proportion to what leaves it, until it reaches a fixed-pressure boundary that is not a vessel (a vent to atmosphere: counted), another vessel (not counted -- it will be back), or a dead end (not counted). Species do not exist in the network, so this is the only way a tank can know whether the vapour it let go is gone.
Definition at line 4814 of file core.py.
References feedtwin.session.burn.Probes.bottles, bottles, min, model, feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, and tanks.
Referenced by _integrate(), _move_vessels(), and _venting().
|
protected |
More of the gas at ``node`` leaves for the sky than arrives or is sent on to another vessel.
Definition at line 4805 of file core.py.
References _split_at(), and _vent_fraction().
Referenced by _ullage_storage().
|
protected |
Definition at line 3854 of file core.py.
References feedtwin.session.burn.Probes.bottles, bottles, feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, and tanks.
Referenced by _integrate().
| None feedtwin.session.core.Session.apply_thermal | ( | self | ) |
Push the thermal knobs in ``setup`` onto vessels already built. The tanks were constructed with whatever the setup said at the time; the console changes it while the stand runs, and a knob that only took effect on the next session was a knob that did not work.
Definition at line 3112 of file core.py.
References feedtwin.session.core._skin_conductance(), anonymous_namespace{idle_e2e.cpp}::World.setup, setup, feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, and tanks.
| dict[str, str] feedtwin.session.core.Session.builtin | ( | self | ) |
The table's rows this stand acts on by name with no valve wired (:func:`builtin_rows`), on the fills it found.
Definition at line 2593 of file core.py.
References _drawn_fill, feedtwin.session.core.builtin_rows(), machine, and model.
| None feedtwin.session.core.Session.command_state | ( | self, | |
| str | state ) |
Definition at line 3152 of file core.py.
References _state_since, binding, forced, machine, anonymous_namespace{idle_e2e.cpp}::Beat.state, anonymous_namespace{idle_e2e.cpp}::World.state, battery_t.state, feedtwin.session.core.BottleSim.state, state, feedtwin.session.core.TankSim.state, gnss_core_t.state, gnss_frame_parser_t.state, SensorHotfire::CoreState.state, Valve.state, world_t.state, anonymous_namespace{idle_e2e.cpp}::Beat.t, anonymous_namespace{idle_e2e.cpp}::World::Ground.t, feedtwin.model.component.EvalContext.t, feedtwin.session.burn.BurnTrace.t, t, gui.App.t, lc_calibration_gui.LCPlotWindow.t, and rec_t.t.
Referenced by _burnout_check().
| dict[str, float] feedtwin.session.core.Session.fire_loads | ( | self | ) |
Propellant a fire is loaded with, per vehicle tank [kg]. The engine's ``fire_load`` (its config's ``lox_tank.mass`` and ``fuel_tank.mass``) on the tank of that side. What the vehicle carries is fixed by the competition, not by the size of the tank drawn, so the pad loads this and T-0 starts with it. Empty without an engine that states one: then loads fill the tank to its full fraction.
Definition at line 2524 of file core.py.
References _fire_loads, model, feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, tanks, and vehicle_tanks().
Referenced by _integrate(), _stop_full_loads(), and short_loads().
| frozenset[str] feedtwin.session.core.Session.ground | ( | self | ) |
Drawing ids of the ground support: everything off the vehicle (:func:`feedtwin.pid.roles.vehicle_ids`). Empty for a drawing that is one piece.
Definition at line 2518 of file core.py.
References feedtwin.session.core._ground(), and model.
| float feedtwin.session.core.Session.inventory | ( | self | ) |
Fluid held in every vessel: liquid, ullage gas, vapour, bottles [kg].
Definition at line 4142 of file core.py.
References feedtwin.session.burn.Probes.bottles, bottles, feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, and tanks.
Referenced by _record_solver(), and reset_balance().
| bool feedtwin.session.core.Session.lit_this_state | ( | self | ) |
Whether the engine has made thrust since the present state began.
Definition at line 5757 of file core.py.
References _lit_at, and _state_since.
Referenced by _burnout_check(), and _fire_notes().
| list[str] feedtwin.session.core.Session.operator_held | ( | self | ) |
Valves a person has taken from the state table, by drawing id. :attr:`forced` holds those, and also the twin's own crew on a drawn load -- the transfer valve it shuts at the start and opens for the load. Shown as the operator's "1 held" on a stand nobody had touched, that read as a bug (the operator, 2026-10-09). A crew valve a person has since turned the other way is the person's again.
Definition at line 3175 of file core.py.
References _fill_crew, and forced.
| dict[str, float] feedtwin.session.core.Session.peek_signals | ( | self, | |
| * | , | ||
| bool | loaded_dome = False ) |
What the components would read now, moving nothing. :meth:`signals` is the step's: it slews each valve toward its command (a zero ``dt`` snaps it there), spends the T-0 dome prime, and records what each dome line holds. A readout must do none of that -- the lockup under the dome knob, asked for on every console tick, snapped every valve to its command mid-travel, so the console's mains opened in one tick whatever their travel time. ``loaded_dome``: read each dome line as open to its loader, the dome the knob sets -- not what a shut line holds (atmosphere, in Idle).
Definition at line 3328 of file core.py.
References _dome_held, _dome_primed, _dome_readings, _positions, feedtwin.comps.base.FlowConditions.signals, feedtwin.model.component.EvalContext.signals, feedtwin.session.core.Sample.signals, and signals().
| None feedtwin.session.core.Session.prime | ( | self, | |
| * | , | ||
| float | fill_fraction = 0.95, | ||
| float | tank_psi = 500.0, | ||
| float | copv_psi = 0.0, | ||
| str | state = "Ready", | ||
| float | hold_s = PAD_HOLD_S, | ||
| Mapping[str, float] | None | loads = None ) |
Put the stand where it is at T-0, without rehearsing the pad. ``hold_s`` is how long the tanks have been loaded [s]. It sets two things the thermal models are exquisitely sensitive to and that ``initial_state`` cannot know: the interface contact time, whose collapse flux goes as ``1/sqrt(t)`` and is fifty kilowatts at a millisecond; and the wall temperature, which on a cryogenic tank has chilled to its contents by the time anybody fires. Built as if freshly filled -- wall at room temperature, interface a moment old -- a LOX tank with collapse and chilldown enabled collapsed from 550 to 411 psig during the study's own settle and read as a violent drop and recovery at ignition. That was the initial condition, not the burn. Loading and pressing through the sequence is the honest way to get here and is what the console does. It is the wrong way to *study* a burn, because pressing the tanks draws on the same bottle the study is about: an under-sized COPV then fails for two reasons at once and the trace cannot tell you which. This sets the initial condition directly -- tanks loaded to ``fill_fraction`` and sitting at ``tank_psi``, bottle at ``copv_psi`` -- so the burn starts from a stated, reproducible state and the only thing being asked is whether the bottle can hold the tanks up. ``loads`` gives the propellant mass [kg] for the tanks it names, in place of ``fill_fraction`` -- for a vehicle whose load is fixed by mass (a competition rule, a measured fill) rather than by a level. A load that would not fit the tank is refused, not clipped.
Definition at line 2931 of file core.py.
References _dome_primed, _guess, _last_flows, _last_isolated, _last_pressures, _state_since, _ullage_wall_T0(), assumptions, feedtwin.session.burn.Probes.bottles, bottles, anonymous_namespace{idle_e2e.cpp}::World.ground, ground, machine, max, reset_balance(), anonymous_namespace{idle_e2e.cpp}::Beat.state, anonymous_namespace{idle_e2e.cpp}::World.state, battery_t.state, feedtwin.session.core.BottleSim.state, state, feedtwin.session.core.TankSim.state, gnss_core_t.state, gnss_frame_parser_t.state, SensorHotfire::CoreState.state, Valve.state, world_t.state, anonymous_namespace{idle_e2e.cpp}::Beat.t, anonymous_namespace{idle_e2e.cpp}::World::Ground.t, feedtwin.model.component.EvalContext.t, feedtwin.session.burn.BurnTrace.t, t, gui.App.t, lc_calibration_gui.LCPlotWindow.t, rec_t.t, feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, and tanks.
| None feedtwin.session.core.Session.release | ( | self, | |
| str | drawing_id = "" ) |
| None feedtwin.session.core.Session.reset_balance | ( | self | ) |
Start the mass balance from the inventory as it stands: after the stand is put somewhere directly (prime, a restored frame) rather than reached through its boundary.
Definition at line 4159 of file core.py.
References _crossed_in, _crossed_out, _guard_J0, _inventory0, _ledger0, _ledger_totals(), inventory(), feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, and tanks.
Referenced by _record_solver(), and prime().
| None feedtwin.session.core.Session.set_valve | ( | self, | |
| str | drawing_id, | ||
| bool | is_open ) |
| list[str] feedtwin.session.core.Session.short_loads | ( | self | ) |
Each vehicle tank too small for the engine's fire load, said. A load stops at the tank's full fraction (``TankSim._wanted``), so a drawn tank that cannot hold its fire load is loaded short, silently, and every burn on the stand is that much shorter than the engine was designed for. Empty when every tank holds its load.
Definition at line 2543 of file core.py.
References fire_loads(), anonymous_namespace{idle_e2e.cpp}::World.setup, setup, feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, and tanks.
| dict[str, float] feedtwin.session.core.Session.signals | ( | self, | |
| float | dt = 0.0 ) |
What the components read this tick: the state, then hand overrides. Valve positions *slew* toward their commanded value rather than snapping to it. A main valve that goes shut-to-open in zero time is a step input into an ullage of half a litre, and the tank pressure dip it produces is a property of the step, not of the stand: the drop comes out several times deeper than the pad shows, and it arrives before the chamber has lit, so the injector sees full tank pressure against ambient and pulls flow no real start ever pulls. Each valve carries a `travel_time`; this is the one place it can be honoured, because the state machine deals in commanded positions and knows nothing of time.
Definition at line 3236 of file core.py.
References _cut_dome_lines, _dome_ports, _dome_primed, _dome_readings, _gated_dome(), _slew(), _through_loader(), binding, forced, hookup, knobs, machine, model, anonymous_namespace{idle_e2e.cpp}::World.setup, setup, anonymous_namespace{idle_e2e.cpp}::Beat.state, anonymous_namespace{idle_e2e.cpp}::World.state, battery_t.state, feedtwin.session.core.BottleSim.state, state, feedtwin.session.core.TankSim.state, gnss_core_t.state, gnss_frame_parser_t.state, SensorHotfire::CoreState.state, Valve.state, and world_t.state.
Referenced by _integrate(), and peek_signals().
| list[str] feedtwin.session.core.Session.skip_chilldown | ( | self, | |
| str | tank_id = "" ) |
Chill a cryogen tank's wall now rather than wait for the load to. A load spends minutes chilling the metal before anything collects -- ~5 on LE4 at the calibrated dewar valve, ~10 on the stand -- and nobody rehearsing waits that out (the team, 2026-10-08). Each vehicle tank, or the one named, gets :meth:`TankSim.skip_chill`; the cart's own vessels are supplies and are left alone. The assumptions say so, so a burn's record shows its pad was cut short. Returns the labels of the tanks it chilled: none when every wall is already cold.
Definition at line 3204 of file core.py.
References assumptions, anonymous_namespace{idle_e2e.cpp}::World.ground, ground, feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, and tanks.
| Sample feedtwin.session.core.Session.step | ( | self, | |
| float | dt ) |
What the operator sees ``dt`` seconds later. Integrated now, Fire included, as a run of :attr:`Setup.live_step` steps -- the Study's grid, with nothing folded to save wall clock. A stand too stiff for real time runs in slow motion rather than on a coarser scheme (docs/PHYSICS-BENCHMARK.md 3.10). A tripped stand holds the frame it tripped on.
Definition at line 5013 of file core.py.
References _integrate(), _shown, max, min, anonymous_namespace{idle_e2e.cpp}::World.setup, setup, feedtwin.session.burn.BurnEnd.tripped, and tripped.
Referenced by engine.pipeline.thermal.wall_conduction.WallModel.advance(), feedtwin.vessels.volume.GasVolume.blowdown(), feedtwin.vessels.tank.Tank.pressurant_for_expulsion(), and engine.pipeline.thermal.wall_conduction.WallModel.soak().
| tuple[str, ...] feedtwin.session.core.Session.vehicle_tanks | ( | self | ) |
The tanks the engine burns from: every tank, less the ground's.
Definition at line 2570 of file core.py.
References anonymous_namespace{idle_e2e.cpp}::World.ground, ground, feedtwin.session.burn.BurnPlan.tanks, feedtwin.session.core.Sample.tanks, and tanks.
Referenced by _burnout_check(), _chamber(), _fire_notes(), and fire_loads().
|
protected |
Definition at line 2343 of file core.py.
Referenced by _boundary_nodes().
|
protected |
Definition at line 2383 of file core.py.
Referenced by _close_chamber().
|
protected |
Definition at line 2405 of file core.py.
Referenced by _chamber().
|
protected |
Definition at line 2344 of file core.py.
Referenced by _advance_once(), _record_solver(), and reset_balance().
|
protected |
Definition at line 2345 of file core.py.
Referenced by _advance_once(), _record_solver(), and reset_balance().
|
protected |
|
protected |
Definition at line 2406 of file core.py.
Referenced by _chamber().
|
protected |
Definition at line 2312 of file core.py.
Referenced by _gated_dome(), and peek_signals().
|
protected |
|
protected |
Definition at line 2317 of file core.py.
Referenced by _gated_dome(), peek_signals(), prime(), and signals().
|
protected |
Definition at line 2315 of file core.py.
Referenced by _gated_dome(), _integrate(), peek_signals(), and signals().
|
protected |
Definition at line 2453 of file core.py.
Referenced by _integrate(), _move_vessels(), _notes(), and builtin().
|
protected |
Definition at line 2497 of file core.py.
Referenced by _stop_full_loads(), and operator_held().
|
protected |
Definition at line 2442 of file core.py.
Referenced by _advance_once().
|
protected |
Definition at line 2491 of file core.py.
Referenced by _dry_branches(), and _find_fill_stops().
|
protected |
Definition at line 2493 of file core.py.
Referenced by _stop_full_loads().
|
protected |
Definition at line 2492 of file core.py.
Referenced by _stop_full_loads().
|
protected |
Definition at line 2434 of file core.py.
Referenced by _apply_vessel_pressures().
|
protected |
Definition at line 2376 of file core.py.
Referenced by fire_loads().
|
protected |
Definition at line 2348 of file core.py.
Referenced by reset_balance().
|
protected |
Definition at line 2359 of file core.py.
Referenced by _accept(), _advance_once(), _press_path_timescale(), _relief_signals(), _solve(), and prime().
|
protected |
Definition at line 2346 of file core.py.
Referenced by _record_solver(), and reset_balance().
|
protected |
Definition at line 2384 of file core.py.
Referenced by _close_chamber(), and _integrate().
|
protected |
Definition at line 2363 of file core.py.
Referenced by _integrate().
|
protected |
Definition at line 2364 of file core.py.
Referenced by _integrate().
|
protected |
Definition at line 2350 of file core.py.
Referenced by _accept(), _advance_once(), _close_chamber(), _firing(), _integrate(), _leaking_notes(), _press_path_timescale(), _ullage_storage(), and prime().
|
protected |
Definition at line 2368 of file core.py.
Referenced by _advance_once(), _move_vessels(), and prime().
|
protected |
|
protected |
Definition at line 2347 of file core.py.
Referenced by _record_solver(), and reset_balance().
|
protected |
Definition at line 2483 of file core.py.
Referenced by _dry_cut(), _move_vessels(), and _ullage_storage().
|
protected |
Definition at line 2332 of file core.py.
Referenced by _integrate(), and lit_this_state().
|
protected |
Definition at line 2309 of file core.py.
Referenced by _slew(), and peek_signals().
|
protected |
Definition at line 2382 of file core.py.
Referenced by _regulator_slopes().
|
protected |
Definition at line 2513 of file core.py.
Referenced by _integrate(), and _relief_signals().
|
protected |
Definition at line 2512 of file core.py.
Referenced by _advance_once(), and _relief_signals().
|
protected |
Definition at line 2507 of file core.py.
Referenced by _advance_once(), _relief_signals(), and _reliefs_on().
|
protected |
Definition at line 2372 of file core.py.
Referenced by _advance_once(), _coupling_timescale(), _integrate(), _move_vessels(), and _rest_ground().
|
protected |
Definition at line 2377 of file core.py.
Referenced by _rest_ground().
|
protected |
|
protected |
|
protected |
Definition at line 2334 of file core.py.
Referenced by _burnout_check(), _fire_notes(), command_state(), lit_this_state(), and prime().
|
protected |
Definition at line 2342 of file core.py.
Referenced by _close_chamber(), _integrate(), _note_solve(), and _record_solver().
|
protected |
Definition at line 2429 of file core.py.
Referenced by _integrate().
|
protected |
Definition at line 2318 of file core.py.
Referenced by _travel_time().
| dict feedtwin.session.core.Session.arriving_enthalpy = {} |
Definition at line 5383 of file core.py.
Referenced by _bottle_inflow_enthalpy(), _pressurant_enthalpy(), and _propagate_temperatures().
| list feedtwin.session.core.Session.assumptions = [] |
Definition at line 2349 of file core.py.
Referenced by _build_vessels(), _find_drawn_fills(), _off_the_dew_line(), _stop_full_loads(), _supply_press(), prime(), skip_chilldown(), and feedtwin.session.model.AssemblyReport.unchecked().
| feedtwin.session.core.Session.binding = binding |
Definition at line 2291 of file core.py.
Referenced by _find_fill_stubs(), _leaking_notes(), _supply_press(), command_state(), and signals().
| dict feedtwin.session.core.Session.bottles = {} |
Definition at line 2432 of file core.py.
Referenced by _apply_vessel_pressures(), _bottle_for(), _boundary_nodes(), _build_vessels(), _check_limits(), _find_fill_stubs(), _integrate(), _ledger_totals(), _loader_supply(), _move_vessels(), _notes(), _propagate_temperatures(), _reliefs_on(), _sealed(), _unreachable_ground(), _vent_fraction(), _vessel_pressures(), inventory(), and prime().
| feedtwin.session.core.Session.burnout = None |
Definition at line 2328 of file core.py.
Referenced by _burnout_check(), and _notes().
| dict feedtwin.session.core.Session.forced = {} |
Definition at line 2307 of file core.py.
Referenced by _gated_dome(), _stop_full_loads(), command_state(), operator_held(), release(), set_valve(), and signals().
| feedtwin.session.core.Session.ground |
Definition at line 5353 of file core.py.
Referenced by _bottle_for(), _build_vessels(), _integrate(), _leaking_notes(), _loader_supply(), _move_vessels(), _notes(), _rest_ground(), _unreachable_ground(), prime(), skip_chilldown(), and vehicle_tanks().
| feedtwin.session.core.Session.gse_ignored = bool(model.meta.get("vehicle_only")) |
Definition at line 2337 of file core.py.
Referenced by _integrate(), and autonomous_calibration_engine.AdaptivePriorEvolution.update_from_sensor().
| feedtwin.session.core.Session.hookup = hookup |
| feedtwin.session.core.Session.id = uuid.uuid4().hex[:12] |
Definition at line 2288 of file core.py.
Referenced by feedtwin.comps.elements.Bend.check(), feedtwin.comps.elements.FlexHose.check(), feedtwin.model.component.ComponentInstance.to_dict(), and backend.routers.layerx.Job.view().
| tuple feedtwin.session.core.Session.knobs |
Definition at line 2297 of file core.py.
Referenced by feedtwin.session.hookup.Hookup.knob_for(), signals(), and feedtwin.session.hookup.Hookup.to_dict().
| feedtwin.session.core.Session.machine = machine |
Definition at line 2290 of file core.py.
Referenced by _burnout_check(), _fire_notes(), _integrate(), _notes(), _supply_press(), builtin(), command_state(), prime(), signals(), and feedtwin.session.hookup.Hookup.to_dict().
| feedtwin.session.core.Session.model = model |
Definition at line 2289 of file core.py.
Referenced by _apply_vessel_pressures(), _arriving_liquid_T(), _boundary_nodes(), _build_vessels(), _burnout_check(), _chamber(), _check_limits(), _close_chamber(), _close_outlet(), _coupling_timescale(), _cut_dome_regulators(), _dry_branches(), _find_cut_dome_lines(), _find_cut_dome_ports(), _find_drawn_fills(), _find_fill_stops(), _find_fill_stubs(), _fire_notes(), _firing(), _gated_dome(), _held(), _integrate(), _leaking_notes(), _move_vessels(), _press_path_timescale(), _propagate_temperatures(), _regulator_slopes(), _reliefs_on(), _rest_ground(), _sealed(), _split_at(), _stop_full_loads(), _supply_press(), _supply_to(), _through_loader(), _through_outlets(), _travel_time(), _ullage_storage(), _unreachable_ground(), _vent_fraction(), builtin(), fire_loads(), ground(), engine.layerx.prepare.Prepared.ok(), signals(), and feedtwin.model.component.ComponentInstance.to_dict().
| feedtwin.session.core.Session.setup = setup or Setup() |
Definition at line 2304 of file core.py.
Referenced by _advance_once(), _bottle_inflow_enthalpy(), _bottle_wall_defaults(), _build_vessels(), _burnout_check(), _close_chamber(), _film_estimator(), _integrate(), _move_vessels(), _notes(), _press_path_timescale(), _pressurant_enthalpy(), _propagate_temperatures(), _rest_ground(), _solve(), _stop_full_loads(), _supply_press(), _tank_wall_defaults(), _travel_time(), _ullage_wall_T0(), apply_thermal(), short_loads(), signals(), and step().
| Deque[SolverRecord] feedtwin.session.core.Session.solver_log = deque(maxlen=HISTORY) |
Definition at line 2339 of file core.py.
Referenced by _record_solver().
| feedtwin.session.core.Session.state = state if state in machine.states else machine.states[0] |
Definition at line 2300 of file core.py.
Referenced by _burnout_check(), _fire_notes(), _integrate(), _loading(), _notes(), _supply_press(), feedtwin.session.network_trace.NetworkTrace.append(), command_state(), prime(), feedtwin.session.network_trace.NetworkTrace.record(), engine.control.robust_ddp.controller.RobustDDPController.reset(), signals(), engine.control.robust_ddp.controller.RobustDDPController.step(), 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().
| float feedtwin.session.core.Session.t = 0.0 |
Definition at line 2335 of file core.py.
Referenced by engine.pipeline.cea_cache.CEAAuxTables._bilinear(), engine.pipeline.cea_cache.CEAAuxTables._build(), _burnout_check(), _check_limits(), engine.pipeline.cea_cache.CEAAuxTables._exit(), _fire_notes(), _integrate(), engine.pipeline.cea_cache.CEAAuxTables._load(), _record_solver(), engine.layerx.flight.InlineAscent.advance(), command_state(), and prime().
| dict feedtwin.session.core.Session.tanks = {} |
Definition at line 2431 of file core.py.
Referenced by _apply_vessel_pressures(), _boundary_nodes(), _build_vessels(), _burnout_check(), _chamber(), _check_limits(), _close_chamber(), _coupling_timescale(), _dry_branches(), _dry_cut(), _find_fill_stubs(), _fire_notes(), _integrate(), _leaking_notes(), _ledger_totals(), _move_vessels(), _notes(), _propagate_temperatures(), _record_solver(), _regulator_slopes(), _reliefs_on(), _sealed(), _stop_full_loads(), _through_outlets(), _ullage_storage(), _unreachable_ground(), _vent_fraction(), _vessel_pressures(), apply_thermal(), fire_loads(), inventory(), prime(), reset_balance(), short_loads(), skip_chilldown(), and vehicle_tanks().
| Trip | None feedtwin.session.core.Session.trip = None |
Definition at line 2326 of file core.py.
Referenced by _check_limits().
| str | None feedtwin.session.core.Session.tripped = None |
Definition at line 2324 of file core.py.
Referenced by _check_limits(), and step().
| dict feedtwin.session.core.Session.wall_temperature = {} |
Definition at line 5379 of file core.py.
Referenced by _propagate_temperatures().
| dict feedtwin.session.core.Session.walls = {} |
Definition at line 5378 of file core.py.
Referenced by _propagate_temperatures().
| feedtwin.session.core.Session.watcher = Watcher() |
Definition at line 2341 of file core.py.
Referenced by _record_solver().