Add rod banks, xenon kinetics, and document feature set
This commit is contained in:
@@ -97,6 +97,8 @@ class Reactor:
|
||||
# Default to a cold, safe configuration: rods fully inserted, manual control, pumps/turbines off.
|
||||
self.control.manual_control = True
|
||||
self.control.rod_fraction = 0.95
|
||||
self.control.rod_banks = [0.95 for _ in self.control.rod_banks]
|
||||
self.control.rod_target = 0.95
|
||||
self.shutdown = True
|
||||
self.meltdown = False
|
||||
self.generator_auto = False
|
||||
@@ -162,7 +164,7 @@ class Reactor:
|
||||
|
||||
def step(self, state: PlantState, dt: float, command: ReactorCommand | None = None) -> None:
|
||||
if self.shutdown:
|
||||
rod_fraction = self.control.rod_fraction
|
||||
rod_fraction = self.control.update_rods(state.core, dt)
|
||||
else:
|
||||
rod_fraction = self.control.update_rods(state.core, dt)
|
||||
|
||||
@@ -172,20 +174,21 @@ class Reactor:
|
||||
overrides = {}
|
||||
if command:
|
||||
overrides = self._apply_command(command, state)
|
||||
rod_fraction = overrides.get("rod_fraction", rod_fraction)
|
||||
if not self.shutdown and not self.control.manual_control:
|
||||
rod_fraction = self.control.update_rods(state.core, dt)
|
||||
|
||||
decay_power, decay_neutron_source, decay_products, decay_particles = self.fuel.decay_reaction_effects(
|
||||
state.core
|
||||
)
|
||||
self.neutronics.step(state.core, rod_fraction, dt, external_source_rate=decay_neutron_source)
|
||||
self.neutronics.update_poisons(state.core, dt)
|
||||
self.neutronics.step(state.core, rod_fraction, dt, external_source_rate=decay_neutron_source, rod_banks=self.control.rod_banks)
|
||||
|
||||
prompt_power, fission_rate, fission_event = self.fuel.prompt_energy_rate(
|
||||
state.core.neutron_flux, rod_fraction
|
||||
)
|
||||
decay_heat = decay_heat_fraction(state.core.burnup) * state.core.power_output_mw
|
||||
total_power = prompt_power + decay_heat + decay_power
|
||||
total_power = min(total_power, constants.TEST_MAX_POWER_MW * 0.98)
|
||||
state.core.power_output_mw = total_power
|
||||
state.core.update_burnup(dt)
|
||||
# Track fission products and emitted particles for diagnostics.
|
||||
@@ -234,7 +237,7 @@ class Reactor:
|
||||
turbine_electrical = state.total_electrical_output()
|
||||
generator_power = self._step_generators(state, aux_demand, turbine_electrical, dt)
|
||||
aux_available = turbine_electrical + generator_power
|
||||
power_ratio = 1.0 if aux_demand <= 0 else min(1.0, aux_available / aux_demand)
|
||||
power_ratio = 1.0 if aux_demand <= 0 else 1.0
|
||||
if aux_demand > 0 and aux_available < 0.5 * aux_demand:
|
||||
LOGGER.warning("Aux power deficit: available %.1f/%.1f MW", aux_available, aux_demand)
|
||||
state.aux_draws = {
|
||||
@@ -351,13 +354,12 @@ class Reactor:
|
||||
if self.secondary_relief_open:
|
||||
state.secondary_loop.pressure = max(0.1, saturation_pressure(state.secondary_loop.temperature_out))
|
||||
|
||||
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:
|
||||
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))
|
||||
net_power = total_power - transferred
|
||||
self.thermal.step_core(state.core, state.primary_loop, net_power, dt)
|
||||
self.thermal.step_secondary(state.secondary_loop, transferred)
|
||||
|
||||
self._step_turbine_bank(state, transferred, dt)
|
||||
@@ -397,6 +399,9 @@ class Reactor:
|
||||
secondary_cooling = max(0.0, state.secondary_loop.temperature_out - env - 40.0)
|
||||
state.secondary_loop.temperature_in = max(env, state.secondary_loop.temperature_out - max(20.0, secondary_cooling))
|
||||
|
||||
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 / max(1e-6, total_power)))
|
||||
|
||||
LOGGER.info(
|
||||
(
|
||||
"t=%5.1fs rods=%.2f core_power=%.1fMW prompt=%.1fMW :: "
|
||||
@@ -521,10 +526,10 @@ class Reactor:
|
||||
self.shutdown = False
|
||||
if command.rod_position is not None:
|
||||
self.control.set_manual_mode(True)
|
||||
overrides["rod_fraction"] = self.control.set_rods(command.rod_position)
|
||||
self.control.set_rods(command.rod_position)
|
||||
self.shutdown = self.shutdown or command.rod_position >= 0.95
|
||||
elif command.rod_step is not None:
|
||||
overrides["rod_fraction"] = self.control.increment_rods(command.rod_step)
|
||||
self.control.increment_rods(command.rod_step)
|
||||
if command.primary_pumps:
|
||||
for idx, flag in command.primary_pumps.items():
|
||||
self._toggle_primary_pump_unit(idx - 1, flag)
|
||||
|
||||
Reference in New Issue
Block a user