diff --git a/src/reactor_sim/dashboard.py b/src/reactor_sim/dashboard.py index ac3b20c..043eed6 100644 --- a/src/reactor_sim/dashboard.py +++ b/src/reactor_sim/dashboard.py @@ -443,6 +443,7 @@ class ReactorDashboard: ) right_y = self._draw_section(right_win, right_y, "Generators", self._generator_lines(state)) right_y = self._draw_section(right_win, right_y, "Power Stats", self._power_lines(state)) + right_y = self._draw_section(right_win, right_y, "Heat Exchanger", self._heat_exchanger_lines(state)) right_y = self._draw_section(right_win, right_y, "Protections / Warnings", self._protection_lines(state)) right_y = self._draw_section(right_win, right_y, "Maintenance", self._maintenance_lines()) self._draw_health_bars(right_win, right_y) @@ -603,6 +604,14 @@ class ReactorDashboard: ] return lines + def _heat_exchanger_lines(self, state: PlantState) -> list[tuple[str, str]]: + delta_t = getattr(state, "primary_to_secondary_delta_t", 0.0) + eff = getattr(state, "heat_exchanger_efficiency", 0.0) + return [ + ("ΔT (pri-sec)", f"{delta_t:6.1f} K"), + ("HX Eff", f"{eff*100:6.1f}%"), + ] + def _protection_lines(self, state: PlantState) -> list[tuple[str, str]]: lines: list[tuple[str, str]] = [] lines.append(("SCRAM", "ACTIVE" if self.reactor.shutdown else "CLEAR")) diff --git a/src/reactor_sim/reactor.py b/src/reactor_sim/reactor.py index a3882d4..d1ae296 100644 --- a/src/reactor_sim/reactor.py +++ b/src/reactor_sim/reactor.py @@ -351,6 +351,8 @@ class Reactor: transferred = 0.0 else: transferred = heat_transfer(state.primary_loop, state.secondary_loop, total_power) + state.primary_to_secondary_delta_t = max(0.0, state.primary_loop.temperature_out - state.secondary_loop.temperature_in) + state.heat_exchanger_efficiency = 0.0 if total_power <= 0 else min(1.0, max(0.0, transferred / total_power)) self.thermal.step_secondary(state.secondary_loop, transferred) self._step_turbine_bank(state, transferred, dt) diff --git a/src/reactor_sim/state.py b/src/reactor_sim/state.py index 0ae53f9..6fa86af 100644 --- a/src/reactor_sim/state.py +++ b/src/reactor_sim/state.py @@ -75,6 +75,8 @@ class PlantState: secondary_pumps: list[PumpState] = field(default_factory=list) generators: list[GeneratorState] = field(default_factory=list) aux_draws: dict[str, float] = field(default_factory=dict) + heat_exchanger_efficiency: float = 0.0 + primary_to_secondary_delta_t: float = 0.0 time_elapsed: float = field(default=0.0) def snapshot(self) -> dict[str, float]: @@ -115,6 +117,8 @@ class PlantState: generators_blob = data.get("generators", []) generators = [GeneratorState(**g) for g in generators_blob] aux_draws = data.get("aux_draws", {}) + hx_eff = data.get("heat_exchanger_efficiency", 0.0) + delta_t = data.get("primary_to_secondary_delta_t", 0.0) return cls( core=CoreState(**core_blob, fission_product_inventory=inventory, emitted_particles=particles), primary_loop=CoolantLoopState(**data["primary_loop"]), @@ -124,5 +128,7 @@ class PlantState: secondary_pumps=[PumpState(**p) for p in sec_pumps_blob], generators=generators, aux_draws=aux_draws, + heat_exchanger_efficiency=hx_eff, + primary_to_secondary_delta_t=delta_t, time_elapsed=data.get("time_elapsed", 0.0), ) diff --git a/src/reactor_sim/thermal.py b/src/reactor_sim/thermal.py index c1b219f..77b20aa 100644 --- a/src/reactor_sim/thermal.py +++ b/src/reactor_sim/thermal.py @@ -18,8 +18,8 @@ def heat_transfer(primary: CoolantLoopState, secondary: CoolantLoopState, core_p if secondary.mass_flow_rate <= 0.0: return 0.0 delta_t = max(0.0, primary.temperature_out - secondary.temperature_in) - # Require a larger temperature difference to push full power across the steam generator. - conductance = 0.02 + # Require a modest temperature difference to push full power across the steam generator. + conductance = 0.05 efficiency = 1.0 - math.exp(-conductance * delta_t) transferred = min(core_power_mw, core_power_mw * efficiency) LOGGER.debug("Heat transfer %.2f MW with ΔT=%.1fK", transferred, delta_t)