|
|
|
|
@ -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
|
|
|
|
|
|