Skip to content

Commit 1517b4f

Browse files
Improve pv power formula
We are using the new dfs, in the component graph, to search for pv power components. That fixes this formula in several graphs, especially nested graphs and graphs with more then one grid meter. Signed-off-by: Matthias Wende <[email protected]>
1 parent 31aa32b commit 1517b4f

File tree

1 file changed

+15
-34
lines changed

1 file changed

+15
-34
lines changed

src/frequenz/sdk/timeseries/_formula_engine/_formula_generators/_pv_power_formula.py

Lines changed: 15 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
from __future__ import annotations
77

88
import logging
9-
from collections import abc
109

1110
from ....microgrid import connection_manager
1211
from ....microgrid.component import ComponentCategory, ComponentMetricId
@@ -33,14 +32,20 @@ def generate(self) -> FormulaEngine[Power]:
3332
"pv-power", ComponentMetricId.ACTIVE_POWER, Power.from_watts
3433
)
3534

36-
pv_components = self._get_pv_power_components()
35+
component_graph = connection_manager.get().component_graph
36+
pv_components = component_graph.dfs(
37+
self._get_grid_component(),
38+
set(),
39+
component_graph.is_pv_chain,
40+
)
41+
3742
if not pv_components:
3843
_logger.warning(
39-
"Unable to find any PV inverters in the component graph. "
44+
"Unable to find any PV components in the component graph. "
4045
"Subscribing to the resampling actor with a non-existing "
4146
"component id, so that `0` values are sent from the formula."
4247
)
43-
# If there are no PV inverters, we have to send 0 values at the same
48+
# If there are no PV components, we have to send 0 values at the same
4449
# frequency as the other streams. So we subscribe with a non-existing
4550
# component id, just to get a `None` message at the resampling interval.
4651
builder.push_component_metric(
@@ -50,11 +55,15 @@ def generate(self) -> FormulaEngine[Power]:
5055

5156
builder.push_oper("(")
5257
builder.push_oper("(")
53-
for idx, comp_id in enumerate(pv_components):
58+
for idx, component in enumerate(pv_components):
5459
if idx > 0:
5560
builder.push_oper("+")
5661

57-
builder.push_component_metric(comp_id, nones_are_zeros=True)
62+
# should only be the case if the component is not a meter
63+
builder.push_component_metric(
64+
component.component_id,
65+
nones_are_zeros=component.category != ComponentCategory.METER,
66+
)
5867
builder.push_oper(")")
5968
if self._config.formula_type == FormulaType.PRODUCTION:
6069
builder.push_oper("*")
@@ -65,31 +74,3 @@ def generate(self) -> FormulaEngine[Power]:
6574
builder.push_clipper(0.0, None)
6675

6776
return builder.build()
68-
69-
def _get_pv_power_components(self) -> abc.Set[int]:
70-
"""Get the component ids of the PV inverters or meters in the component graph.
71-
72-
Returns:
73-
A set of component ids of the PV inverters or meters in the component graph.
74-
75-
Raises:
76-
RuntimeError: if the grid component has no PV inverters or meters as successors.
77-
"""
78-
component_graph = connection_manager.get().component_graph
79-
grid_successors = self._get_grid_component_successors()
80-
81-
if len(grid_successors) == 1:
82-
successor = next(iter(grid_successors))
83-
if successor.category != ComponentCategory.METER:
84-
raise RuntimeError(
85-
"Only grid successor in the component graph is not a meter."
86-
)
87-
grid_successors = component_graph.successors(successor.component_id)
88-
89-
pv_meters_or_inverters: set[int] = set()
90-
91-
for successor in grid_successors:
92-
if component_graph.is_pv_chain(successor):
93-
pv_meters_or_inverters.add(successor.component_id)
94-
95-
return pv_meters_or_inverters

0 commit comments

Comments
 (0)