Improve persistence and reactor dynamics
This commit is contained in:
@@ -30,6 +30,15 @@ class ComponentHealth:
|
||||
self.failed = True
|
||||
LOGGER.error("Component %s has failed", self.name)
|
||||
|
||||
def restore(self, amount: float) -> None:
|
||||
if amount <= 0.0:
|
||||
return
|
||||
previous = self.integrity
|
||||
self.integrity = min(1.0, self.integrity + amount)
|
||||
if self.integrity > 0.05:
|
||||
self.failed = False
|
||||
LOGGER.info("Maintenance on %s: %.3f -> %.3f", self.name, previous, self.integrity)
|
||||
|
||||
def snapshot(self) -> dict:
|
||||
return asdict(self)
|
||||
|
||||
@@ -46,8 +55,10 @@ class HealthMonitor:
|
||||
"core": ComponentHealth("core"),
|
||||
"primary_pump": ComponentHealth("primary_pump"),
|
||||
"secondary_pump": ComponentHealth("secondary_pump"),
|
||||
"turbine": ComponentHealth("turbine"),
|
||||
}
|
||||
for idx in range(3):
|
||||
name = f"turbine_{idx + 1}"
|
||||
self.components[name] = ComponentHealth(name)
|
||||
self.failure_log: list[str] = []
|
||||
|
||||
def component(self, name: str) -> ComponentHealth:
|
||||
@@ -58,10 +69,11 @@ class HealthMonitor:
|
||||
state: PlantState,
|
||||
primary_active: bool,
|
||||
secondary_active: bool,
|
||||
turbine_active: bool,
|
||||
turbine_active: Iterable[bool],
|
||||
dt: float,
|
||||
) -> List[str]:
|
||||
events: list[str] = []
|
||||
turbine_flags = list(turbine_active)
|
||||
core = self.component("core")
|
||||
core_temp = state.core.fuel_temperature
|
||||
temp_stress = max(0.0, (core_temp - 900.0) / (constants.MAX_CORE_TEMPERATURE - 900.0))
|
||||
@@ -82,17 +94,23 @@ class HealthMonitor:
|
||||
else:
|
||||
self.component("secondary_pump").degrade(0.0005 * dt)
|
||||
|
||||
if turbine_active:
|
||||
electrical = state.turbine.electrical_output_mw
|
||||
load_ratio = (
|
||||
0.0
|
||||
if state.turbine.load_demand_mw <= 0
|
||||
else min(1.0, electrical / max(1e-6, state.turbine.load_demand_mw))
|
||||
)
|
||||
stress = 0.0002 + abs(1 - load_ratio) * 0.003
|
||||
self.component("turbine").degrade(stress * dt)
|
||||
else:
|
||||
self.component("turbine").degrade(0.0001 * dt)
|
||||
turbines = state.turbines if hasattr(state, "turbines") else []
|
||||
for idx, active in enumerate(turbine_flags):
|
||||
name = f"turbine_{idx + 1}"
|
||||
component = self.component(name)
|
||||
if active and idx < len(turbines):
|
||||
turbine_state = turbines[idx]
|
||||
demand = turbine_state.load_demand_mw
|
||||
supplied = turbine_state.load_supplied_mw
|
||||
if demand <= 0:
|
||||
load_ratio = 0.0
|
||||
else:
|
||||
load_ratio = min(1.0, supplied / max(1e-6, demand))
|
||||
mismatch = abs(1 - load_ratio)
|
||||
stress = 0.00005 + mismatch * 0.0006
|
||||
else:
|
||||
stress = 0.00002
|
||||
component.degrade(stress * dt)
|
||||
|
||||
for name, component in self.components.items():
|
||||
if component.failed and name not in self.failure_log:
|
||||
@@ -105,6 +123,14 @@ class HealthMonitor:
|
||||
|
||||
def load_snapshot(self, data: dict) -> None:
|
||||
for name, comp_data in data.items():
|
||||
if name in self.components:
|
||||
self.components[name] = ComponentHealth.from_snapshot(comp_data)
|
||||
mapped = "turbine_1" if name == "turbine" else name
|
||||
if mapped in self.components:
|
||||
self.components[mapped] = ComponentHealth.from_snapshot(comp_data)
|
||||
|
||||
def maintain(self, component: str, amount: float = 0.05) -> bool:
|
||||
comp = self.components.get(component)
|
||||
if not comp:
|
||||
LOGGER.warning("Maintenance requested for unknown component %s", component)
|
||||
return False
|
||||
comp.restore(amount)
|
||||
return True
|
||||
|
||||
Reference in New Issue
Block a user