Show per-pump status and per-turbine output
This commit is contained in:
@@ -275,7 +275,8 @@ class ReactorDashboard:
|
||||
y,
|
||||
"Primary Loop",
|
||||
[
|
||||
("Pump", "ON" if self.reactor.primary_pump_active else "OFF"),
|
||||
("Pump1", self._pump_status(state.primary_pumps, 0)),
|
||||
("Pump2", self._pump_status(state.primary_pumps, 1)),
|
||||
("Flow", f"{state.primary_loop.mass_flow_rate:7.0f} kg/s"),
|
||||
("Inlet Temp", f"{state.primary_loop.temperature_in:7.1f} K"),
|
||||
("Outlet Temp", f"{state.primary_loop.temperature_out:7.1f} K"),
|
||||
@@ -287,7 +288,8 @@ class ReactorDashboard:
|
||||
y,
|
||||
"Secondary Loop",
|
||||
[
|
||||
("Pump", "ON" if self.reactor.secondary_pump_active else "OFF"),
|
||||
("Pump1", self._pump_status(state.secondary_pumps, 0)),
|
||||
("Pump2", self._pump_status(state.secondary_pumps, 1)),
|
||||
("Flow", f"{state.secondary_loop.mass_flow_rate:7.0f} kg/s"),
|
||||
("Inlet Temp", f"{state.secondary_loop.temperature_in:7.1f} K"),
|
||||
("Pressure", f"{state.secondary_loop.pressure:5.2f} MPa"),
|
||||
@@ -305,6 +307,15 @@ class ReactorDashboard:
|
||||
"Turbine / Grid",
|
||||
[
|
||||
("Turbines", " ".join(self._turbine_status_lines())),
|
||||
("Unit1 Elec", f"{state.turbines[0].electrical_output_mw:7.1f} MW" if state.turbines else "n/a"),
|
||||
(
|
||||
"Unit2 Elec",
|
||||
f"{state.turbines[1].electrical_output_mw:7.1f} MW" if len(state.turbines) > 1 else "n/a",
|
||||
),
|
||||
(
|
||||
"Unit3 Elec",
|
||||
f"{state.turbines[2].electrical_output_mw:7.1f} MW" if len(state.turbines) > 2 else "n/a",
|
||||
),
|
||||
("Electrical", f"{state.total_electrical_output():7.1f} MW"),
|
||||
("Load", f"{self._total_load_supplied(state):7.1f}/{self._total_load_demand(state):7.1f} MW"),
|
||||
("Consumer", f"{consumer_status}"),
|
||||
@@ -421,6 +432,12 @@ class ReactorDashboard:
|
||||
return [("Active", "None")]
|
||||
return [(comp, "IN PROGRESS") for comp in sorted(self.reactor.maintenance_active)]
|
||||
|
||||
def _pump_status(self, pumps: list, index: int) -> str:
|
||||
if index >= len(pumps):
|
||||
return "n/a"
|
||||
state = pumps[index]
|
||||
return f"{'ON ' if state.active else 'OFF'} {state.flow_rate:6.0f} kg/s"
|
||||
|
||||
def _draw_health_bar(self, win: "curses._CursesWindow", start_y: int) -> None:
|
||||
height, width = win.getmaxyx()
|
||||
if start_y >= height - 2:
|
||||
|
||||
@@ -14,7 +14,7 @@ from .control import ControlSystem
|
||||
from .failures import HealthMonitor
|
||||
from .fuel import FuelAssembly, decay_heat_fraction
|
||||
from .neutronics import NeutronDynamics
|
||||
from .state import CoolantLoopState, CoreState, PlantState, TurbineState
|
||||
from .state import CoolantLoopState, CoreState, PlantState, PumpState, TurbineState
|
||||
from .thermal import ThermalSolver, heat_transfer
|
||||
from .turbine import SteamGenerator, Turbine
|
||||
|
||||
@@ -102,6 +102,8 @@ class Reactor:
|
||||
mass_flow_rate=0.0,
|
||||
steam_quality=0.0,
|
||||
)
|
||||
primary_pumps = [PumpState(active=self.primary_pump_active, flow_rate=0.0, pressure=0.5) for _ in range(2)]
|
||||
secondary_pumps = [PumpState(active=self.secondary_pump_active, flow_rate=0.0, pressure=0.5) for _ in range(2)]
|
||||
turbine_states = [
|
||||
TurbineState(
|
||||
steam_enthalpy=2_000.0,
|
||||
@@ -113,7 +115,14 @@ class Reactor:
|
||||
)
|
||||
for _ in self.turbines
|
||||
]
|
||||
return PlantState(core=core, primary_loop=primary, secondary_loop=secondary, turbines=turbine_states)
|
||||
return PlantState(
|
||||
core=core,
|
||||
primary_loop=primary,
|
||||
secondary_loop=secondary,
|
||||
turbines=turbine_states,
|
||||
primary_pumps=primary_pumps,
|
||||
secondary_pumps=secondary_pumps,
|
||||
)
|
||||
|
||||
def step(self, state: PlantState, dt: float, command: ReactorCommand | None = None) -> None:
|
||||
if self.shutdown:
|
||||
@@ -151,15 +160,41 @@ class Reactor:
|
||||
|
||||
pump_demand = overrides.get("coolant_demand", self.control.coolant_demand(state.primary_loop))
|
||||
if self.primary_pump_active:
|
||||
self.primary_pump.step(state.primary_loop, pump_demand)
|
||||
total_flow = 0.0
|
||||
pressure = 12.0 * pump_demand + 2.0
|
||||
for pump_state in state.primary_pumps:
|
||||
flow = self.primary_pump.flow_rate(pump_demand)
|
||||
pump_state.active = True
|
||||
pump_state.flow_rate = flow
|
||||
pump_state.pressure = pressure
|
||||
total_flow += flow
|
||||
state.primary_loop.mass_flow_rate = total_flow
|
||||
state.primary_loop.pressure = pressure
|
||||
else:
|
||||
state.primary_loop.mass_flow_rate = 0.0
|
||||
state.primary_loop.pressure = 0.5
|
||||
for pump_state in state.primary_pumps:
|
||||
pump_state.active = False
|
||||
pump_state.flow_rate = 0.0
|
||||
pump_state.pressure = state.primary_loop.pressure
|
||||
if self.secondary_pump_active:
|
||||
self.secondary_pump.step(state.secondary_loop, 0.75)
|
||||
total_flow = 0.0
|
||||
pressure = 12.0 * 0.75 + 2.0
|
||||
for pump_state in state.secondary_pumps:
|
||||
flow = self.secondary_pump.flow_rate(0.75)
|
||||
pump_state.active = True
|
||||
pump_state.flow_rate = flow
|
||||
pump_state.pressure = pressure
|
||||
total_flow += flow
|
||||
state.secondary_loop.mass_flow_rate = total_flow
|
||||
state.secondary_loop.pressure = pressure
|
||||
else:
|
||||
state.secondary_loop.mass_flow_rate = 0.0
|
||||
state.secondary_loop.pressure = 0.5
|
||||
for pump_state in state.secondary_pumps:
|
||||
pump_state.active = False
|
||||
pump_state.flow_rate = 0.0
|
||||
pump_state.pressure = state.secondary_loop.pressure
|
||||
|
||||
self.thermal.step_core(state.core, state.primary_loop, total_power, dt)
|
||||
if not self.secondary_pump_active or state.secondary_loop.mass_flow_rate <= 1.0:
|
||||
|
||||
@@ -54,12 +54,21 @@ class TurbineState:
|
||||
load_supplied_mw: float = 0.0
|
||||
|
||||
|
||||
@dataclass
|
||||
class PumpState:
|
||||
active: bool
|
||||
flow_rate: float
|
||||
pressure: float
|
||||
|
||||
|
||||
@dataclass
|
||||
class PlantState:
|
||||
core: CoreState
|
||||
primary_loop: CoolantLoopState
|
||||
secondary_loop: CoolantLoopState
|
||||
turbines: list[TurbineState]
|
||||
primary_pumps: list[PumpState] = field(default_factory=list)
|
||||
secondary_pumps: list[PumpState] = field(default_factory=list)
|
||||
time_elapsed: float = field(default=0.0)
|
||||
|
||||
def snapshot(self) -> dict[str, float]:
|
||||
@@ -73,6 +82,8 @@ class PlantState:
|
||||
"turbine_electric": self.total_electrical_output(),
|
||||
"products": self.core.fission_product_inventory,
|
||||
"particles": self.core.emitted_particles,
|
||||
"primary_pumps": [pump.active for pump in self.primary_pumps],
|
||||
"secondary_pumps": [pump.active for pump in self.secondary_pumps],
|
||||
}
|
||||
|
||||
def total_electrical_output(self) -> float:
|
||||
@@ -92,10 +103,14 @@ class PlantState:
|
||||
old_turbine = data.get("turbine")
|
||||
turbines_blob = [old_turbine] if old_turbine else []
|
||||
turbines = [TurbineState(**t) for t in turbines_blob]
|
||||
prim_pumps_blob = data.get("primary_pumps", [])
|
||||
sec_pumps_blob = data.get("secondary_pumps", [])
|
||||
return cls(
|
||||
core=CoreState(**core_blob, fission_product_inventory=inventory, emitted_particles=particles),
|
||||
primary_loop=CoolantLoopState(**data["primary_loop"]),
|
||||
secondary_loop=CoolantLoopState(**data["secondary_loop"]),
|
||||
turbines=turbines,
|
||||
primary_pumps=[PumpState(**p) for p in prim_pumps_blob],
|
||||
secondary_pumps=[PumpState(**p) for p in sec_pumps_blob],
|
||||
time_elapsed=data.get("time_elapsed", 0.0),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user