Add SCRAM matrix (DNB/subcool/SG limits) and clad split
This commit is contained in:
@@ -761,6 +761,12 @@ class ReactorDashboard:
|
||||
if self.reactor.secondary_relief_open:
|
||||
reliefs.append("Secondary")
|
||||
lines.append(("Relief valves", ", ".join(reliefs) if reliefs else "Closed"))
|
||||
lines.append(
|
||||
(
|
||||
"SCRAM trips",
|
||||
"DNB<0.5 | Subcool<2K | SG lvl<5/>98% | SG P>15.2MPa",
|
||||
)
|
||||
)
|
||||
return lines
|
||||
|
||||
def _steam_available_power(self, state: PlantState) -> float:
|
||||
|
||||
@@ -435,12 +435,25 @@ class Reactor:
|
||||
|
||||
if (not self.secondary_pump_active or state.secondary_loop.mass_flow_rate <= 1.0) and total_power > 50.0:
|
||||
self._handle_heat_sink_loss(state)
|
||||
if state.core.dnb_margin is not None and state.core.dnb_margin < 0.3:
|
||||
# SCRAM matrix: DNB, subcooling, steam generator level/pressure
|
||||
if state.core.dnb_margin is not None and state.core.dnb_margin < 0.5:
|
||||
LOGGER.critical("DNB margin low: %.2f, initiating SCRAM", state.core.dnb_margin)
|
||||
self.shutdown = True
|
||||
self.control.scram()
|
||||
if state.core.subcooling_margin is not None and state.core.subcooling_margin < 5.0:
|
||||
if state.core.subcooling_margin is not None and state.core.subcooling_margin < 2.0:
|
||||
LOGGER.critical("Subcooling margin lost: %.1fK, initiating SCRAM", state.core.subcooling_margin)
|
||||
self.shutdown = True
|
||||
self.control.scram()
|
||||
elif state.core.subcooling_margin is not None and state.core.subcooling_margin < 5.0:
|
||||
LOGGER.warning("Subcooling margin low: %.1fK", state.core.subcooling_margin)
|
||||
if state.secondary_loop.level < 0.05 or state.secondary_loop.level > 0.98:
|
||||
LOGGER.critical("Secondary level out of bounds (%.1f%%), initiating SCRAM", state.secondary_loop.level * 100)
|
||||
self.shutdown = True
|
||||
self.control.scram()
|
||||
if state.secondary_loop.pressure > 0.95 * constants.MAX_PRESSURE:
|
||||
LOGGER.critical("Secondary pressure high (%.2f MPa), initiating SCRAM", state.secondary_loop.pressure)
|
||||
self.shutdown = True
|
||||
self.control.scram()
|
||||
|
||||
failures = self.health_monitor.evaluate(
|
||||
state,
|
||||
|
||||
@@ -119,9 +119,15 @@ class ThermalSolver:
|
||||
heating = (0.002 * max(0.0, power_mw) + 0.01 * max(0.0, residual_power_mw)) * dt
|
||||
cooling = 0.025 * max(0.0, core.fuel_temperature - primary.temperature_out) * dt
|
||||
core.fuel_temperature += heating - cooling
|
||||
# Simple clad/fuel split: clad lags fuel and is cooled by coolant.
|
||||
clad = core.clad_temperature or primary.temperature_out
|
||||
conduction = 0.02 * max(0.0, core.fuel_temperature - clad) * dt
|
||||
clad_cooling = 0.05 * max(0.0, clad - primary.temperature_out) * dt
|
||||
clad = max(primary.temperature_out, clad + conduction - clad_cooling)
|
||||
core.fuel_temperature = max(primary.temperature_out, core.fuel_temperature - conduction)
|
||||
# Keep fuel temperature bounded and never below the coolant outlet temperature.
|
||||
core.fuel_temperature = min(max(primary.temperature_out, core.fuel_temperature), constants.MAX_CORE_TEMPERATURE)
|
||||
core.clad_temperature = max(primary.temperature_out, core.clad_temperature or primary.temperature_out)
|
||||
core.fuel_temperature = min(core.fuel_temperature, constants.MAX_CORE_TEMPERATURE)
|
||||
core.clad_temperature = min(clad, constants.MAX_CORE_TEMPERATURE)
|
||||
core.subcooling_margin = max(0.0, saturation_temperature(primary.pressure) - primary.temperature_out)
|
||||
chf = self._critical_heat_flux(primary)
|
||||
heat_flux = (power_mw * constants.MEGAWATT) / max(1.0, self._core_surface_area())
|
||||
|
||||
Reference in New Issue
Block a user