Skip to content

Commit db4365a

Browse files
authored
Improve code reusability/modularity in PowerDistributor (#717)
This PR prepares the classes and functions to be reused better for upcoming changes in the context of nm inverters. refs #501
2 parents 3c5e727 + ada9202 commit db4365a

File tree

6 files changed

+336
-407
lines changed

6 files changed

+336
-407
lines changed

src/frequenz/sdk/actor/power_distributing/_distribution_algorithm/_distribution_algorithm.py

Lines changed: 66 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@
66
import logging
77
import math
88
from dataclasses import dataclass
9-
from typing import NamedTuple
9+
from typing import NamedTuple, Sequence
1010

1111
from ...._internal._math import is_close_to_zero
1212
from ....microgrid.component import BatteryData, InverterData
13+
from ..result import PowerBounds
1314

1415
_logger = logging.getLogger(__name__)
1516

@@ -36,17 +37,8 @@ class AggregatedBatteryData:
3637
soc_lower_bound: float
3738
"""The aggregated lower SoC bound of the batteries."""
3839

39-
power_inclusion_upper_bound: float
40-
"""The aggregated upper power inclusion bound of the batteries."""
41-
42-
power_inclusion_lower_bound: float
43-
"""The aggregated lower power inclusion bound of the batteries."""
44-
45-
power_exclusion_upper_bound: float
46-
"""The aggregated upper power exclusion bound of the batteries."""
47-
48-
power_exclusion_lower_bound: float
49-
"""The aggregated lower power exclusion bound of the batteries."""
40+
power_bounds: PowerBounds
41+
"""The aggregated power bounds of the batteries."""
5042

5143
def __init__(self, batteries: list[BatteryData]) -> None:
5244
"""Create DistBatteryData from BatteryData.
@@ -63,7 +55,7 @@ def __init__(self, batteries: list[BatteryData]) -> None:
6355
Args:
6456
batteries: The batteries to aggregate.
6557
"""
66-
assert len(batteries) > 0, "No batteries given."
58+
assert len(batteries) > 0, "AggregatedBatteryData: No batteries given."
6759

6860
# We need only one component ID for DistBatteryData to be able to
6961
# identify the pair
@@ -84,21 +76,58 @@ def __init__(self, batteries: list[BatteryData]) -> None:
8476
self.soc_upper_bound = math.nan
8577
self.soc_lower_bound = math.nan
8678

87-
self.power_inclusion_upper_bound = sum(
88-
b.power_inclusion_upper_bound for b in batteries
89-
)
90-
self.power_inclusion_lower_bound = sum(
91-
b.power_inclusion_lower_bound for b in batteries
79+
self.power_bounds = _aggregate_battery_power_bounds(
80+
list(
81+
map(
82+
lambda metrics: PowerBounds(
83+
inclusion_upper=metrics.power_inclusion_upper_bound,
84+
inclusion_lower=metrics.power_inclusion_lower_bound,
85+
exclusion_upper=metrics.power_exclusion_upper_bound,
86+
exclusion_lower=metrics.power_exclusion_lower_bound,
87+
),
88+
batteries,
89+
)
90+
)
9291
)
93-
# To satisfy the largest exclusion bounds in the set we need to
94-
# provide the power defined by the largest bounds multiplied by the
95-
# number of batteries in the set.
96-
self.power_exclusion_upper_bound = max(
97-
b.power_exclusion_upper_bound for b in batteries
98-
) * len(batteries)
99-
self.power_exclusion_lower_bound = min(
100-
b.power_exclusion_lower_bound for b in batteries
101-
) * len(batteries)
92+
93+
94+
def _aggregate_battery_power_bounds(
95+
battery_metrics: Sequence[PowerBounds],
96+
) -> PowerBounds:
97+
"""Calculate bounds for a set of batteries located behind one set of inverters.
98+
99+
Args:
100+
battery_metrics: List of PowerBounds for each battery.
101+
102+
Returns:
103+
A PowerBounds object containing the aggregated bounds for all given batteries
104+
"""
105+
assert len(battery_metrics) > 0, "No batteries given."
106+
107+
# Calculate the aggregated bounds for the set of batteries
108+
power_inclusion_upper_bound = sum(
109+
bounds.inclusion_upper for bounds in battery_metrics
110+
)
111+
power_inclusion_lower_bound = sum(
112+
bounds.inclusion_lower for bounds in battery_metrics
113+
)
114+
115+
# To satisfy the largest exclusion bounds in the set we need to
116+
# provide the power defined by the largest bounds multiplied by the
117+
# number of batteries in the set.
118+
power_exclusion_upper_bound = max(
119+
bounds.exclusion_upper for bounds in battery_metrics
120+
) * len(battery_metrics)
121+
power_exclusion_lower_bound = min(
122+
bounds.exclusion_lower for bounds in battery_metrics
123+
) * len(battery_metrics)
124+
125+
return PowerBounds(
126+
inclusion_lower=power_inclusion_lower_bound,
127+
exclusion_lower=power_exclusion_lower_bound,
128+
exclusion_upper=power_exclusion_upper_bound,
129+
inclusion_upper=power_inclusion_upper_bound,
130+
)
102131

103132

104133
class InvBatPair(NamedTuple):
@@ -752,17 +781,21 @@ def _inclusion_exclusion_bounds(
752781
excl_bounds: dict[int, float] = {}
753782
for battery, inverters in components:
754783
if supply:
755-
excl_bounds[battery.component_id] = -battery.power_exclusion_lower_bound
756-
incl_bounds[battery.component_id] = -battery.power_inclusion_lower_bound
784+
excl_bounds[
785+
battery.component_id
786+
] = -battery.power_bounds.exclusion_lower
787+
incl_bounds[
788+
battery.component_id
789+
] = -battery.power_bounds.inclusion_lower
757790
else:
758-
excl_bounds[battery.component_id] = battery.power_exclusion_upper_bound
759-
incl_bounds[battery.component_id] = battery.power_inclusion_upper_bound
791+
excl_bounds[battery.component_id] = battery.power_bounds.exclusion_upper
792+
incl_bounds[battery.component_id] = battery.power_bounds.inclusion_upper
760793

761794
for inverter in inverters:
762795
if supply:
763796
incl_bounds[inverter.component_id] = -max(
764797
inverter.active_power_inclusion_lower_bound,
765-
battery.power_inclusion_lower_bound,
798+
battery.power_bounds.inclusion_lower,
766799
)
767800
excl_bounds[
768801
inverter.component_id
@@ -771,7 +804,7 @@ def _inclusion_exclusion_bounds(
771804
else:
772805
incl_bounds[inverter.component_id] = min(
773806
inverter.active_power_inclusion_upper_bound,
774-
battery.power_inclusion_upper_bound,
807+
battery.power_bounds.inclusion_upper,
775808
)
776809
excl_bounds[
777810
inverter.component_id

0 commit comments

Comments
 (0)