diff --git a/src/reactor_sim/commands.py b/src/reactor_sim/commands.py index 158395d..91e11fa 100644 --- a/src/reactor_sim/commands.py +++ b/src/reactor_sim/commands.py @@ -21,6 +21,8 @@ class ReactorCommand: consumer_demand: float | None = None rod_manual: bool | None = None turbine_units: dict[int, bool] | None = None + primary_pumps: dict[int, bool] | None = None + secondary_pumps: dict[int, bool] | None = None maintenance_components: tuple[str, ...] = tuple() @classmethod diff --git a/src/reactor_sim/dashboard.py b/src/reactor_sim/dashboard.py index de3b46b..c5eae62 100644 --- a/src/reactor_sim/dashboard.py +++ b/src/reactor_sim/dashboard.py @@ -51,6 +51,10 @@ class ReactorDashboard: DashboardKey("space", "SCRAM"), DashboardKey("p", "Toggle primary pump"), DashboardKey("o", "Toggle secondary pump"), + DashboardKey("g", "Toggle primary pump 1"), + DashboardKey("h", "Toggle primary pump 2"), + DashboardKey("j", "Toggle secondary pump 1"), + DashboardKey("k", "Toggle secondary pump 2"), DashboardKey("t", "Toggle turbine"), DashboardKey("1/2/3", "Toggle turbine units 1-3"), DashboardKey("y/u/i", "Maintain turbine 1/2/3"), @@ -126,6 +130,14 @@ class ReactorDashboard: self._queue_command(ReactorCommand(primary_pump_on=not self.reactor.primary_pump_active)) elif ch in (ord("o"), ord("O")): self._queue_command(ReactorCommand(secondary_pump_on=not self.reactor.secondary_pump_active)) + elif ch in (ord("g"), ord("G")): + self._toggle_primary_pump_unit(0) + elif ch in (ord("h"), ord("H")): + self._toggle_primary_pump_unit(1) + elif ch in (ord("j"), ord("J")): + self._toggle_secondary_pump_unit(0) + elif ch in (ord("k"), ord("K")): + self._toggle_secondary_pump_unit(1) elif ch in (ord("t"), ord("T")): self._queue_command(ReactorCommand(turbine_on=not self.reactor.turbine_active)) elif ord("1") <= ch <= ord("9"): diff --git a/src/reactor_sim/reactor.py b/src/reactor_sim/reactor.py index bc46b5e..73499d4 100644 --- a/src/reactor_sim/reactor.py +++ b/src/reactor_sim/reactor.py @@ -36,6 +36,8 @@ class Reactor: health_monitor: HealthMonitor = field(default_factory=HealthMonitor) primary_pump_active: bool = True secondary_pump_active: bool = True + primary_pump_units: list[bool] = field(default_factory=lambda: [True, True]) + secondary_pump_units: list[bool] = field(default_factory=lambda: [True, True]) turbine_active: bool = True turbine_unit_active: list[bool] = field(default_factory=lambda: [True, True, True]) shutdown: bool = False @@ -48,6 +50,10 @@ class Reactor: if not self.turbine_unit_active or len(self.turbine_unit_active) != len(self.turbines): self.turbine_unit_active = [True] * len(self.turbines) self.turbine_active = any(self.turbine_unit_active) + if not self.primary_pump_units or len(self.primary_pump_units) != 2: + self.primary_pump_units = [True, True] + if not self.secondary_pump_units or len(self.secondary_pump_units) != 2: + self.secondary_pump_units = [True, True] @classmethod def default(cls) -> "Reactor": @@ -162,12 +168,17 @@ class Reactor: if self.primary_pump_active: 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 + for idx, pump_state in enumerate(state.primary_pumps): + if idx < len(self.primary_pump_units) and self.primary_pump_units[idx]: + flow = self.primary_pump.flow_rate(pump_demand) + pump_state.active = True + pump_state.flow_rate = flow + pump_state.pressure = pressure + total_flow += flow + else: + pump_state.active = False + pump_state.flow_rate = 0.0 + pump_state.pressure = state.primary_loop.pressure state.primary_loop.mass_flow_rate = total_flow state.primary_loop.pressure = pressure else: @@ -180,12 +191,17 @@ class Reactor: if self.secondary_pump_active: 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 + for idx, pump_state in enumerate(state.secondary_pumps): + if idx < len(self.secondary_pump_units) and self.secondary_pump_units[idx]: + flow = self.secondary_pump.flow_rate(0.75) + pump_state.active = True + pump_state.flow_rate = flow + pump_state.pressure = pressure + total_flow += flow + else: + pump_state.active = False + pump_state.flow_rate = 0.0 + pump_state.pressure = state.secondary_loop.pressure state.secondary_loop.mass_flow_rate = total_flow state.secondary_loop.pressure = pressure else: @@ -313,6 +329,12 @@ class Reactor: self._set_primary_pump(command.primary_pump_on) if command.secondary_pump_on is not None: self._set_secondary_pump(command.secondary_pump_on) + if command.primary_pumps: + for idx, flag in command.primary_pumps.items(): + self._toggle_primary_pump_unit(idx - 1, flag) + if command.secondary_pumps: + for idx, flag in command.secondary_pumps.items(): + self._toggle_secondary_pump_unit(idx - 1, flag) if command.turbine_on is not None: self._set_turbine_state(command.turbine_on) if command.turbine_units: @@ -333,11 +355,19 @@ class Reactor: if self.primary_pump_active != active: self.primary_pump_active = active LOGGER.info("Primary pump %s", "enabled" if active else "stopped") + if not active: + self.primary_pump_units = [False] * len(self.primary_pump_units) + elif active and not any(self.primary_pump_units): + self.primary_pump_units = [True] * len(self.primary_pump_units) def _set_secondary_pump(self, active: bool) -> None: if self.secondary_pump_active != active: self.secondary_pump_active = active LOGGER.info("Secondary pump %s", "enabled" if active else "stopped") + if not active: + self.secondary_pump_units = [False] * len(self.secondary_pump_units) + elif active and not any(self.secondary_pump_units): + self.secondary_pump_units = [True] * len(self.secondary_pump_units) def _set_turbine_state(self, active: bool, index: int | None = None) -> None: if index is None: @@ -423,6 +453,8 @@ class Reactor: metadata = { "primary_pump_active": self.primary_pump_active, "secondary_pump_active": self.secondary_pump_active, + "primary_pump_units": self.primary_pump_units, + "secondary_pump_units": self.secondary_pump_units, "turbine_active": self.turbine_active, "turbine_units": self.turbine_unit_active, "shutdown": self.shutdown, @@ -439,6 +471,8 @@ class Reactor: plant, metadata, health = self.control.load_state(filepath) self.primary_pump_active = metadata.get("primary_pump_active", self.primary_pump_active) self.secondary_pump_active = metadata.get("secondary_pump_active", self.secondary_pump_active) + self.primary_pump_units = list(metadata.get("primary_pump_units", self.primary_pump_units)) + self.secondary_pump_units = list(metadata.get("secondary_pump_units", self.secondary_pump_units)) unit_states = metadata.get("turbine_units") if unit_states: self.turbine_unit_active = list(unit_states)