Expose heat exchanger diagnostics and retune conductance

This commit is contained in:
Codex Agent
2025-11-23 11:05:36 +01:00
parent 4861fa4320
commit 01fec1df42
4 changed files with 19 additions and 2 deletions

View File

@@ -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, "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, "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, "Protections / Warnings", self._protection_lines(state))
right_y = self._draw_section(right_win, right_y, "Maintenance", self._maintenance_lines()) right_y = self._draw_section(right_win, right_y, "Maintenance", self._maintenance_lines())
self._draw_health_bars(right_win, right_y) self._draw_health_bars(right_win, right_y)
@@ -603,6 +604,14 @@ class ReactorDashboard:
] ]
return lines 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]]: def _protection_lines(self, state: PlantState) -> list[tuple[str, str]]:
lines: list[tuple[str, str]] = [] lines: list[tuple[str, str]] = []
lines.append(("SCRAM", "ACTIVE" if self.reactor.shutdown else "CLEAR")) lines.append(("SCRAM", "ACTIVE" if self.reactor.shutdown else "CLEAR"))

View File

@@ -351,6 +351,8 @@ class Reactor:
transferred = 0.0 transferred = 0.0
else: else:
transferred = heat_transfer(state.primary_loop, state.secondary_loop, total_power) 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.thermal.step_secondary(state.secondary_loop, transferred)
self._step_turbine_bank(state, transferred, dt) self._step_turbine_bank(state, transferred, dt)

View File

@@ -75,6 +75,8 @@ class PlantState:
secondary_pumps: list[PumpState] = field(default_factory=list) secondary_pumps: list[PumpState] = field(default_factory=list)
generators: list[GeneratorState] = field(default_factory=list) generators: list[GeneratorState] = field(default_factory=list)
aux_draws: dict[str, float] = field(default_factory=dict) 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) time_elapsed: float = field(default=0.0)
def snapshot(self) -> dict[str, float]: def snapshot(self) -> dict[str, float]:
@@ -115,6 +117,8 @@ class PlantState:
generators_blob = data.get("generators", []) generators_blob = data.get("generators", [])
generators = [GeneratorState(**g) for g in generators_blob] generators = [GeneratorState(**g) for g in generators_blob]
aux_draws = data.get("aux_draws", {}) 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( 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"]),
@@ -124,5 +128,7 @@ class PlantState:
secondary_pumps=[PumpState(**p) for p in sec_pumps_blob], secondary_pumps=[PumpState(**p) for p in sec_pumps_blob],
generators=generators, generators=generators,
aux_draws=aux_draws, aux_draws=aux_draws,
heat_exchanger_efficiency=hx_eff,
primary_to_secondary_delta_t=delta_t,
time_elapsed=data.get("time_elapsed", 0.0), time_elapsed=data.get("time_elapsed", 0.0),
) )

View File

@@ -18,8 +18,8 @@ def heat_transfer(primary: CoolantLoopState, secondary: CoolantLoopState, core_p
if secondary.mass_flow_rate <= 0.0: if secondary.mass_flow_rate <= 0.0:
return 0.0 return 0.0
delta_t = max(0.0, primary.temperature_out - secondary.temperature_in) delta_t = max(0.0, primary.temperature_out - secondary.temperature_in)
# Require a larger temperature difference to push full power across the steam generator. # Require a modest temperature difference to push full power across the steam generator.
conductance = 0.02 conductance = 0.05
efficiency = 1.0 - math.exp(-conductance * delta_t) efficiency = 1.0 - math.exp(-conductance * delta_t)
transferred = min(core_power_mw, core_power_mw * efficiency) transferred = min(core_power_mw, core_power_mw * efficiency)
LOGGER.debug("Heat transfer %.2f MW with ΔT=%.1fK", transferred, delta_t) LOGGER.debug("Heat transfer %.2f MW with ΔT=%.1fK", transferred, delta_t)