Source code for assetra.metrics

from abc import ABC, abstractmethod

from assetra.simulation import ProbabilisticSimulation


[docs] class ResourceAdequacyMetric(ABC): """Class responsible for quantifying resource adequacy of a ProbabilisticSimulation object Args: simulation (ProbabilisticSimulation) : Simulation object to characterize. """ def __init__(self, simulation: ProbabilisticSimulation): self.simulation = simulation
[docs] @abstractmethod def evaluate(self) -> float: """Return resource adequacy of initialized simulation. Returns: float: Evaluated resource adequacy metric. """ pass
[docs] class ExpectedUnservedEnergy(ResourceAdequacyMetric): """Derived ResourceAdequacyMetric class responsible for calculating expected unserved energy: "[The] total expected amount of unserved energy ... in a given study horizon." https://gridops.epri.com/Adequacy/metrics#Magnitude_Metrics Args: simulation (ProbabilisticSimulation) : Simulation object to characterize. """
[docs] def evaluate(self) -> float: """Return expected unserved energy Returns: float: EUE in units of energy """ hourly_unserved_energy = ( self.simulation.net_hourly_capacity_matrix.where( self.simulation.net_hourly_capacity_matrix < 0, 0 ) ) return float( -hourly_unserved_energy.sum() / hourly_unserved_energy.sizes["trial"] )
[docs] class LossOfLoadHours(ResourceAdequacyMetric): """Derived ResourceAdequacyMetric class responsible for calculating loss of load hours: "[The] expected count of event-hours per study horizon." https://gridops.epri.com/Adequacy/metrics#Loss_of_Load_Hours_.28LOLH.29 Args: simulation (ProbabilisticSimulation) : Simulation object to characterize. """
[docs] def evaluate(self) -> float: """Return loss of load hours Returns: float: LOLH in units of hours """ hourly_outages = self.simulation.net_hourly_capacity_matrix < 0 return float(hourly_outages.sum() / hourly_outages.sizes["trial"])
[docs] class LossOfLoadDays(ResourceAdequacyMetric): """Derived ResourceAdequacyMetric class responsible for calculating loss of load days: "[The] expected count of event-days per study horizon." https://gridops.epri.com/Adequacy/metrics#Loss_of_Load_Days_.28LOLD.2C_LOLEd.2Fyr.29 Args: simulation (ProbabilisticSimulation) : Simulation object to characterize. """
[docs] def evaluate(self) -> float: """Return loss of load days Returns: float: LOLD in units of days """ hourly_outages = self.simulation.net_hourly_capacity_matrix < 0 daily_outages = hourly_outages.resample(time="1D").max() return float(daily_outages.sum() / hourly_outages.sizes["trial"])
[docs] class LossOfLoadFrequency(ResourceAdequacyMetric): """Derived ResourceAdequacyMetric class responsible for calculating loss of load frequency: "[The] expected count of adequacy events per study horizon, with an adequacy event defined as a contiguous set of hours with a shortfall https://gridops.epri.com/Adequacy/metrics#Loss_of_Load_Events_.28LOLEv.2C_LOLF.29 Args: simulation (ProbabilisticSimulation) : Simulation object to characterize. """
[docs] def evaluate(self) -> float: """Return loss of load frequency Returns: float: LOLF in units of # of events """ hourly_outages = ( self.simulation.net_hourly_capacity_matrix < 0 ).astype(int) shifted_hourly_outages = hourly_outages.roll(time=1) hourly_outage_transitions = ( hourly_outages - shifted_hourly_outages ) > 0 return float( (hourly_outage_transitions.sum() + hourly_outages[:, -1].sum()) / hourly_outages.sizes["trial"] )