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