fix rbd calculation

main
Cizz22 5 months ago
parent 204e49ba73
commit 7fbb61344a

@ -119,6 +119,8 @@ class AerosSimulationCalcResult(Base, DefaultMixin):
average_level = Column(Float, nullable=True)
potential_production = Column(Float, nullable=True)
eaf = Column(Float, nullable=True)
efor = Column(Float, nullable=True)
derating_hours = Column(Float, nullable=True)
eta = Column(Float, nullable=True)
beta = Column(Float, nullable=True)
mttr = Column(Integer, nullable=True)

@ -28,7 +28,8 @@ from .service import (
get_simulation_with_calc_result,
get_simulation_with_plot_result,
update_simulation,
get_result_ranking
get_result_ranking,
get_plant_calc_result
)
from src.aeros_equipment.schema import EquipmentWithCustomParameters
@ -123,6 +124,23 @@ async def get_simulation_result(db_session: DbSession, simulation_id, schematic_
"message": "Simulation result retrieved successfully",
}
@router.get(
"/result/calc/{simulation_id}/plant",
response_model=StandardResponse[SimulationCalc],
)
async def get_simulation_result_plant(db_session: DbSession, simulation_id):
"""Get simulation result."""
simulation_result = await get_plant_calc_result(
db_session=db_session, simulation_id=simulation_id
)
return {
"data": simulation_result,
"status": "success",
"message": "Simulation result retrieved successfully",
}
@router.get(
"/result/plot/{simulation_id}",

@ -233,6 +233,15 @@ async def save_simulation_result(
db_session=db_session, node_data=result, type="calc"
)
eaf, derating_hours = calculate_eaf(
available_hours=result["totalUpTime"],
period_hours=result["totalUpTime"] + result["totalDowntime"],
actual_production=result["production"],
ideal_production=result["idealProduction"]
)
efor = (result["totalDowntime"] / (result["totalDowntime"] + result["totalUpTime"])*100) if (result["totalDowntime"] + result["totalUpTime"]) > 0 else 0
calc_result = AerosSimulationCalcResult(
aeros_simulation_id=simulation_id,
aeros_node_id=node.id,
@ -266,7 +275,9 @@ async def save_simulation_result(
stg_output=result["stgOutput"],
average_level=result["averageLevel"],
potential_production=result["potentialProduction"],
eaf=result["production"] / result["idealProduction"] if result["idealProduction"] > 0 else 0,
eaf=eaf,
efor=efor,
derating_hours=derating_hours,
beta=eq_reliability["beta"] if node_type == "RegularNode" else None,
eta=eq_reliability["eta"] if node_type == "RegularNode" else None,
mttr=eq_reliability["mttr"] if node_type == "RegularNode" else None,
@ -514,6 +525,23 @@ async def get_simulation_with_calc_result(
return simulation.scalars().all()
async def get_plant_calc_result(
*, db_session, simulation_id: UUID
):
query = (select(AerosSimulationCalcResult).filter(
AerosSimulationCalcResult.aeros_simulation_id == simulation_id,
).join(AerosNode, AerosNode.id == AerosSimulationCalcResult.aeros_node_id)
.filter(AerosNode.node_name == "- TJB - Unit 3 -"))
query = query.options(
selectinload(AerosSimulationCalcResult.aeros_node).options(
selectinload(AerosNode.equipment)
))
calc = await db_session.execute(query)
return calc.scalar_one_or_none()
async def get_result_ranking(*, db_session: DbSession, simulation_id: UUID):
query = select(AerosEquipment, AerosSimulationCalcResult.eaf).join(AerosNode, AerosNode.node_name == AerosEquipment.node_name).join(AerosSimulationCalcResult, AerosSimulationCalcResult.aeros_node_id == AerosNode.id)

@ -0,0 +1,54 @@
def calculate_eaf(
available_hours: float,
period_hours: float,
actual_production: float,
ideal_production: float
) -> Dict[str, float]:
"""
Calculate EAF using the time-based method from PLN document
EAF = [AH - (EFDH + EMDH + EPDH + ESEDH)] / PH × 100%
Args:
available_hours: Available Hours (AH)
period_hours: Period Hours (PH)
max_capacity_mw: Maximum capacity in MW
actual_production: Actual production
ideal_production: Ideal production
Returns:
Dictionary with EAF result and breakdown
"""
# Calculate lost production
lost_production = ideal_production - actual_production
estimated_max_capacity = ideal_production / period_hours if period_hours > 0 else 0
# Calculate total equivalent derate hours
total_equivalent_derate_hours = lost_production / estimated_max_capacity
# Calculate EAF
effective_available_hours = available_hours - total_equivalent_derate_hours
return (effective_available_hours / period_hours) * 100, total_equivalent_derate_hours
# def calculate_efor(
# forced_outage_hours: float,
# service_hours: float,
# synchronous_hours: float,
# equivalent_forced_derate_hours: float,
# equivalent_forced_derate_hours_rs: float = 0.0
# ) -> Dict[str, float]:
# """
# Calculate EFOR (Equivalent Forced Outage Rate) according to PLN standards
# EFOR = (FOH) / (TH) × 100%
# """
# # Calculate FOR (Forced Outage Rate)
# # FOR = FOH / (FOH + SH + Synchronous Hours) × 100%
# denominator_for = forced_outage_hours + service_hours + synchronous_hours
# for_rate = (forced_outage_hours / denominator_for * 100) if denominator_for > 0 else 0
# # Calculate EFOR (Equivalent Forced Outage Rate)
# # EFOR = (FOH + EFDH) / (FOH + SH + Synchr.Hrs + EFDHRS) × 100%
# numerator_efor = forced_outage_hours + equivalent_forced_derate_hours
# denominator_efor = forced_outage_hours + service_hours + synchronous_hours + equivalent_forced_derate_hours_rs
# return (numerator_efor / denominator_efor * 100) if denominator_efor > 0 else 0
Loading…
Cancel
Save