Compare commits
3 Commits
03595b0d12
...
4162ecf712
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4162ecf712 | ||
|
|
bf744a07a5 | ||
|
|
afa8997614 |
5
TODO.md
5
TODO.md
@@ -7,3 +7,8 @@
|
|||||||
- [ ] Introduce CHF/DNB margin, clad/fuel split temps, and SCRAM matrix for subcooling loss or SG level/pressure trips.
|
- [ ] Introduce CHF/DNB margin, clad/fuel split temps, and SCRAM matrix for subcooling loss or SG level/pressure trips.
|
||||||
- [ ] Flesh out condenser behavior: vacuum pump limits, cooling water temperature coupling, and dynamic back-pressure with fouling.
|
- [ ] Flesh out condenser behavior: vacuum pump limits, cooling water temperature coupling, and dynamic back-pressure with fouling.
|
||||||
- [ ] Dashboard polish: compact turbine/generator rows, color critical warnings (SCRAM/heat-sink), and reduce repeated log noise.
|
- [ ] Dashboard polish: compact turbine/generator rows, color critical warnings (SCRAM/heat-sink), and reduce repeated log noise.
|
||||||
|
- [ ] Incremental realism plan:
|
||||||
|
- Add stored enthalpy for primary/secondary loops and a steam-drum mass/energy balance (sensible + latent) while keeping existing pump logic and tests passing.
|
||||||
|
- Adjust HX/pressure handling to use stored energy (saturation clamp and pressure rise) and validate steam formation with both pumps at ~3 GW.
|
||||||
|
- Update turbine power mapping to consume steam enthalpy/quality and align protection trips with real steam presence.
|
||||||
|
- Add integration test: cold start → gens/pumps 2/2 → ramp to ~3 GW → confirm steam quality threshold → enable all turbines and require electrical output.
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ MEV_TO_J = 1.602_176_634e-13
|
|||||||
ELECTRON_FISSION_CROSS_SECTION = 5e-16 # cm^2, tuned for simulation scale
|
ELECTRON_FISSION_CROSS_SECTION = 5e-16 # cm^2, tuned for simulation scale
|
||||||
PUMP_SPOOL_TIME = 5.0 # seconds to reach commanded flow
|
PUMP_SPOOL_TIME = 5.0 # seconds to reach commanded flow
|
||||||
PRIMARY_PUMP_SHUTOFF_HEAD_MPA = 8.0 # approximate shutoff head for primary pumps
|
PRIMARY_PUMP_SHUTOFF_HEAD_MPA = 8.0 # approximate shutoff head for primary pumps
|
||||||
SECONDARY_PUMP_SHUTOFF_HEAD_MPA = 7.0
|
SECONDARY_PUMP_SHUTOFF_HEAD_MPA = 3.0
|
||||||
TURBINE_SPOOL_TIME = 12.0 # seconds to reach steady output
|
TURBINE_SPOOL_TIME = 12.0 # seconds to reach steady output
|
||||||
|
|
||||||
# Turbine/condenser parameters
|
# Turbine/condenser parameters
|
||||||
|
|||||||
@@ -324,7 +324,8 @@ class Reactor:
|
|||||||
pump_state.status = "STOPPING" if pump_state.flow_rate > 0.1 else "OFF"
|
pump_state.status = "STOPPING" if pump_state.flow_rate > 0.1 else "OFF"
|
||||||
if self.secondary_pump_active:
|
if self.secondary_pump_active:
|
||||||
total_flow = 0.0
|
total_flow = 0.0
|
||||||
base_flow, base_head = self.secondary_pump.performance(0.75)
|
demand = 0.75
|
||||||
|
base_flow, base_head = self.secondary_pump.performance(demand)
|
||||||
target_pressure = max(0.5, base_head * power_ratio)
|
target_pressure = max(0.5, base_head * power_ratio)
|
||||||
loop_pressure = max(0.1, saturation_pressure(state.secondary_loop.temperature_out))
|
loop_pressure = max(0.1, saturation_pressure(state.secondary_loop.temperature_out))
|
||||||
target_flow = base_flow * power_ratio
|
target_flow = base_flow * power_ratio
|
||||||
@@ -428,8 +429,10 @@ class Reactor:
|
|||||||
)
|
)
|
||||||
state.secondary_loop.temperature_in = state.secondary_loop.temperature_out
|
state.secondary_loop.temperature_in = state.secondary_loop.temperature_out
|
||||||
else:
|
else:
|
||||||
secondary_cooling = max(0.0, state.secondary_loop.temperature_out - env - 40.0)
|
# Allow the secondary to retain more heat so it can approach saturation and form steam.
|
||||||
state.secondary_loop.temperature_in = max(env, state.secondary_loop.temperature_out - max(20.0, secondary_cooling))
|
excess = max(0.0, state.secondary_loop.temperature_out - env)
|
||||||
|
cooling_drop = min(40.0, max(10.0, 0.2 * excess))
|
||||||
|
state.secondary_loop.temperature_in = max(env, state.secondary_loop.temperature_out - cooling_drop)
|
||||||
|
|
||||||
state.primary_to_secondary_delta_t = max(0.0, state.primary_loop.temperature_out - state.secondary_loop.temperature_in)
|
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)))
|
state.heat_exchanger_efficiency = 0.0 if total_power <= 0 else min(1.0, max(0.0, transferred / max(1e-6, total_power)))
|
||||||
|
|||||||
@@ -18,12 +18,17 @@ class CoreState:
|
|||||||
reactivity_margin: float # delta rho
|
reactivity_margin: float # delta rho
|
||||||
power_output_mw: float # MW thermal
|
power_output_mw: float # MW thermal
|
||||||
burnup: float # fraction of fuel consumed
|
burnup: float # fraction of fuel consumed
|
||||||
|
clad_temperature: float | None = None # Kelvin
|
||||||
xenon_inventory: float = 0.0
|
xenon_inventory: float = 0.0
|
||||||
iodine_inventory: float = 0.0
|
iodine_inventory: float = 0.0
|
||||||
delayed_precursors: list[float] = field(default_factory=list)
|
delayed_precursors: list[float] = field(default_factory=list)
|
||||||
fission_product_inventory: dict[str, float] = field(default_factory=dict)
|
fission_product_inventory: dict[str, float] = field(default_factory=dict)
|
||||||
emitted_particles: dict[str, float] = field(default_factory=dict)
|
emitted_particles: dict[str, float] = field(default_factory=dict)
|
||||||
|
|
||||||
|
def __post_init__(self) -> None:
|
||||||
|
if self.clad_temperature is None:
|
||||||
|
self.clad_temperature = self.fuel_temperature
|
||||||
|
|
||||||
def update_burnup(self, dt: float) -> None:
|
def update_burnup(self, dt: float) -> None:
|
||||||
produced_energy_mwh = self.power_output_mw * (dt / 3600.0)
|
produced_energy_mwh = self.power_output_mw * (dt / 3600.0)
|
||||||
self.burnup = clamp(self.burnup + produced_energy_mwh * 1e-5, 0.0, 0.99)
|
self.burnup = clamp(self.burnup + produced_energy_mwh * 1e-5, 0.0, 0.99)
|
||||||
@@ -111,6 +116,10 @@ class PlantState:
|
|||||||
core_blob = dict(data["core"])
|
core_blob = dict(data["core"])
|
||||||
inventory = core_blob.pop("fission_product_inventory", {})
|
inventory = core_blob.pop("fission_product_inventory", {})
|
||||||
particles = core_blob.pop("emitted_particles", {})
|
particles = core_blob.pop("emitted_particles", {})
|
||||||
|
# Backwards/forwards compatibility for optional core fields.
|
||||||
|
core_blob.pop("dnb_margin", None)
|
||||||
|
core_blob.pop("subcooling_margin", None)
|
||||||
|
core_blob.setdefault("clad_temperature", core_blob.get("fuel_temperature", 295.0))
|
||||||
turbines_blob = data.get("turbines")
|
turbines_blob = data.get("turbines")
|
||||||
if turbines_blob is None:
|
if turbines_blob is None:
|
||||||
# Compatibility with previous single-turbine snapshots.
|
# Compatibility with previous single-turbine snapshots.
|
||||||
|
|||||||
Reference in New Issue
Block a user