feat: replace static maintenance downtime with dynamic manual maintenance outage calculations

main
Cizz22 3 months ago
parent d85155feb3
commit 9c8c3ae7a6

@ -27,6 +27,7 @@ class SimulationInput(DefultBase):
OverhaulDuration: Optional[int] = Field(1200)
AhmJobId: Optional[str] = Field(None, max_length=50)
deratings: Optional[List[dict]] = []
maintenance_outages: Optional[List[dict]] = []
class SimulationNode(DefultBase):
id: UUID

@ -252,7 +252,7 @@ async def create_calc_result_object(
async def calculate_plant_eaf(
db_session: DbSession, simulation_id: UUID, mo_downtime: int, po_downtime:int, oh_interval:int, offset:int, manual_deratings: list = None
db_session: DbSession, simulation_id: UUID, po_downtime:int, oh_interval:int, offset:int, manual_deratings: list = None, manual_mo: list = None
):
"""Calculate overall plant EAF from individual node results."""
plant_calc_data = await get_plant_calc_result(
@ -268,17 +268,33 @@ async def calculate_plant_eaf(
) > oh_interval
# Calculate manual MO hours (full outage) and MD hours (derating)
manual_mo_outage_hours = 0.0
manual_mo_equiv_hours = 0.0
max_capacity = 630
if manual_mo:
for mo in manual_mo:
h = float(mo.get('hours', 0))
c = float(mo.get('capacity', 0))
if c <= 0:
manual_mo_outage_hours += h
else:
derating = max_capacity - c
if derating > 0:
manual_mo_equiv_hours += (h * derating / max_capacity)
# Calculate outages
if is_oh_from_aeros:
seasonal_outage = (mo_downtime) * 24 + po_downtime
forced_outage = max(0, plant_calc_data.total_downtime - (po_downtime))
seasonal_outage = manual_mo_outage_hours + po_downtime
forced_outage = max(0, plant_calc_data.total_downtime - po_downtime)
else:
seasonal_outage = mo_downtime * 24
seasonal_outage = manual_mo_outage_hours
forced_outage = max(0, plant_calc_data.total_downtime)
# Adjust uptime
total_uptime = max(0, plant_calc_data.total_uptime - (mo_downtime * 24))
total_uptime = max(0, plant_calc_data.total_uptime - manual_mo_outage_hours)
# Total period time
total_period_time = total_uptime + seasonal_outage + forced_outage
@ -293,9 +309,15 @@ async def calculate_plant_eaf(
manual_deratings=manual_deratings
)
# # Adjust EAF and edh for manual MO deratings
# if manual_mo_equiv_hours > 0:
# # eaf remains reduced by both edh and manual_mo_equiv_hours
# eaf = ((total_uptime - (edh + manual_mo_equiv_hours)) / total_period_time) * 100
# # maintenance deratings should contribute to scheduled metrics (SOF/ESOF)
# sof = ((seasonal_outage + manual_mo_equiv_hours) / total_period_time) * 100
# edh += manual_mo_equiv_hours
plant_calc_data.total_mo_downtime = mo_downtime
plant_calc_data.total_mo_downtime = manual_mo_outage_hours
plant_calc_data.total_po_downtime = po_downtime
plant_calc_data.eaf = eaf
plant_calc_data.efor = efor

@ -62,11 +62,11 @@ async def calculate_plant_eaf_activity(params: dict):
return await calculate_plant_eaf(
db_session=db_session,
simulation_id=params["HubCnnId"],
mo_downtime=params["MaintenanceOutages"],
po_downtime=params["OverhaulDuration"],
oh_interval=params["OverhaulInterval"],
offset=params["OffSet"],
manual_deratings=params.get("deratings", [])
manual_deratings=params.get("deratings", []),
manual_mo=params.get("maintenance_outages", [])
)

Loading…
Cancel
Save