Skip to content

Commit

Permalink
Add components (islands) view with Load Flow results
Browse files Browse the repository at this point in the history
Signed-off-by: Damien Jeandemange <[email protected]>
  • Loading branch information
jeandemanged committed Nov 24, 2024
1 parent 586dac0 commit 9fb446b
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 3 deletions.
3 changes: 3 additions & 0 deletions yagat/frames/impl/base_list_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ def __init__(self, column_name: str, editable: bool = False):
'ac_interchange': DoubleColumnFormat('ac_interchange', precision=PRECISION_POWER),
'dc_interchange': DoubleColumnFormat('dc_interchange', precision=PRECISION_POWER),
'ac': BooleanColumnFormat('ac'),
'iteration_count': IntegerColumnFormat('iteration_count'),
'active_power_mismatch': DoubleColumnFormat('active_power_mismatch', precision=PRECISION_POWER),
'distributed_active_power': DoubleColumnFormat('distributed_active_power', precision=PRECISION_POWER),
}


Expand Down
39 changes: 39 additions & 0 deletions yagat/frames/impl/components_list_view.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#
# Copyright (c) 2024, Damien Jeandemange (https://github.com/jeandemanged)
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# SPDX-License-Identifier: MPL-2.0
#
from typing import Any

import pandas as pd

from yagat.app_context import AppContext
from yagat.frames.impl.base_list_view import BaseListView, BaseColumnFormat


class ComponentsListView(BaseListView):

def __init__(self, parent, context: AppContext, *args, **kwargs):
BaseListView.__init__(self, parent, context, *args, **kwargs)

@property
def tab_name(self) -> str:
return 'Components (Islands)'

@property
def tab_group_name(self) -> str:
return 'Components (Islands)'

def get_data_frame(self) -> pd.DataFrame:
return self.context.network_structure.components

def get_column_formats(self) -> dict[str, BaseColumnFormat]:
return super().get_column_formats()

def on_entry(self, ident: str, column_name: str, new_value: Any):
raise RuntimeError('Components do not support update')

def filter_data_frame(self, df: pd.DataFrame, voltage_levels: list[str]) -> pd.DataFrame:
return df
1 change: 1 addition & 0 deletions yagat/frames/impl/logs_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ def __init__(self, parent, *args, **kwargs):
logging.info(_pypowsybl.get_version_table())

def emit(self, record):
# FIXME: slowing down everything !
msg = self.format(record)
self.sheet.insert_row(row=[record.asctime, record.levelname, msg], idx=0)
if record.levelname == 'WARNING':
Expand Down
2 changes: 2 additions & 0 deletions yagat/frames/impl/tabs_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from yagat.app_context import AppContext
from yagat.frames.impl.area_boundaries_list_view import AreaBoundariesListView
from yagat.frames.impl.area_list_view import AreaListView
from yagat.frames.impl.components_list_view import ComponentsListView
from yagat.frames.impl.diagram_view_bus import DiagramViewBus
from yagat.frames.impl.buses_bus_view_list_view import BusesListView
from yagat.frames.impl.buses_bus_breaker_view_list_view import BusesBusBreakerViewListView
Expand Down Expand Up @@ -60,6 +61,7 @@ def __init__(self, parent, context: AppContext, *args, **kwargs):
self._add_tab(HvdcLineView(self.tab_control, self.context))
self._add_tab(AreaListView(self.tab_control, self.context))
self._add_tab(AreaBoundariesListView(self.tab_control, self.context))
self._add_tab(ComponentsListView(self.tab_control, self.context))

self.tab_control.pack(expand=True, fill=tk.BOTH)

Expand Down
10 changes: 7 additions & 3 deletions yagat/menus/impl/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,14 @@ def on_done():

def task():
if ac:
results = lf.run_ac(self.context.network, parameters=self.context.lf_parameters, reporter=reporter)
lf_components_results = lf.run_ac(self.context.network,
parameters=self.context.lf_parameters,
reporter=reporter)
else:
results = lf.run_dc(self.context.network, parameters=self.context.lf_parameters, reporter=reporter)
print(results)
lf_components_results = lf.run_dc(self.context.network,
parameters=self.context.lf_parameters,
reporter=reporter)
self.context.network_structure.lf_components_results = lf_components_results
print(reporter)

self.context.start_long_running_task(name='Load Flow', target=task, on_done=on_done)
3 changes: 3 additions & 0 deletions yagat/menus/impl/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ def __init__(self, parent, context: AppContext, *args, **kwargs):
self.add_command(label='Areas',
command=lambda: self.update_view_and_tab_group('TreeAndTabs', 'Areas List'))
self.add_separator()
self.add_command(label='Components (Islands)',
command=lambda: self.update_view_and_tab_group('TreeAndTabs', 'Components (Islands)'))
self.add_separator()
self.add_command(label='Load Flow Parameters', command=self.view_load_flow_parameters)
self.add_separator()
self.add_command(label='Logs', command=self.view_logs)
Expand Down
46 changes: 46 additions & 0 deletions yagat/networkstructure/impl/network_structure.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
import logging
from typing import Dict, List, Optional, Tuple, Union

import numpy as np
import pandas as pd
import pypowsybl.loadflow as lf
import pypowsybl.network as pn

import yagat.networkstructure as ns
Expand Down Expand Up @@ -38,6 +40,9 @@ def __init__(self, network: pn.Network):
self._linear_shunt_compensator_sections_df: pd.DataFrame = pd.DataFrame()
self._non_linear_shunt_compensator_sections_df: pd.DataFrame = pd.DataFrame()

self._components_df: pd.DataFrame = pd.DataFrame()
self._lf_components_results: list[lf.ComponentResult] = []

self._bus_breaker_topology_cache: Dict[str, pn.BusBreakerTopology] = {}

self.refresh()
Expand Down Expand Up @@ -106,6 +111,14 @@ def __init__(self, network: pn.Network):
def network(self) -> pn.Network:
return self._network

@property
def lf_components_results(self) -> list[lf.ComponentResult]:
return self._lf_components_results

@lf_components_results.setter
def lf_components_results(self, value: list[lf.ComponentResult]) -> None:
self._lf_components_results = value

@property
def areas(self) -> pd.DataFrame:
return self._areas_df
Expand Down Expand Up @@ -174,6 +187,10 @@ def tie_lines(self) -> pd.DataFrame:
def hvdc_lines(self) -> pd.DataFrame:
return self._hvdc_lines_df

@property
def components(self) -> pd.DataFrame:
return self._components_df

def refresh(self):
logging.info('refresh start')

Expand Down Expand Up @@ -208,6 +225,35 @@ def refresh(self):
.merge(tmp, left_on='voltage_level_id', right_on='id', how='left')
.set_index('id'))

logging.info('building components ...')
components = list(zip(self._buses_df.connected_component, self._buses_df.synchronous_component))
components.sort()
components = [f'CC{connected_component} SC{synchronous_component}'
for (connected_component, synchronous_component) in components]
df = pd.DataFrame(index=components)
df = df[~df.index.duplicated(keep='first')]
new_columns = {'status': [''] * len(df),
'status_text': [''] * len(df),
'iteration_count': [np.nan] * len(df),
'reference_bus_id': [''] * len(df),
'slack_buses_ids': [''] * len(df),
'active_power_mismatch': [np.nan] * len(df),
'distributed_active_power': [np.nan] * len(df),
}
self._components_df = df.assign(**new_columns)

for cr in self._lf_components_results:
cid = f'CC{cr.connected_component_num} SC{cr.synchronous_component_num}'
self._components_df.loc[cid, 'status'] = cr.status.name
self._components_df.loc[cid, 'status_text'] = cr.status_text
self._components_df.loc[cid, 'iteration_count'] = cr.iteration_count
self._components_df.loc[cid, 'reference_bus_id'] = cr.reference_bus_id
self._components_df.loc[cid, 'slack_buses_ids'] = ','.join([sbr.id for sbr in cr.slack_bus_results])
self._components_df.loc[cid, 'active_power_mismatch'] = (
sum(sbr.active_power_mismatch for sbr in cr.slack_bus_results)
)
self._components_df.loc[cid, 'distributed_active_power'] = cr.distributed_active_power

logging.info('get_bus_breaker_view_buses')
self._buses_bus_breaker_view_df = (self._network.get_bus_breaker_view_buses()
.reset_index()
Expand Down

0 comments on commit 9fb446b

Please sign in to comment.