Skip to content

Commit

Permalink
wip loadflow parameters
Browse files Browse the repository at this point in the history
Signed-off-by: Damien Jeandemange <[email protected]>
  • Loading branch information
jeandemanged committed Nov 10, 2024
1 parent 9f17835 commit 43279fc
Show file tree
Hide file tree
Showing 3 changed files with 157 additions and 72 deletions.
Binary file modified requirements.in
Binary file not shown.
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ pywin32-ctypes==0.2.3
# via pyinstaller
six==1.16.0
# via python-dateutil
tksheet==7.2.21
# via -r requirements.in
tzdata==2024.2
# via pandas
wcwidth==0.2.13
Expand Down
227 changes: 155 additions & 72 deletions yagat/frames/impl/load_flow_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,150 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# SPDX-License-Identifier: MPL-2.0
#
import idlelib.tooltip as itooltip
import logging
import os
import textwrap
import tkinter as tk
from tkinter import ttk

import pypowsybl.loadflow as lf
import tksheet as tks
from pypowsybl._pypowsybl import BalanceType, VoltageInitMode, ConnectedComponentMode

from yagat.app_context import AppContext
from yagat.frames.impl.vertical_scrolled_frame import VerticalScrolledFrame


class LoadFlowParametersView(VerticalScrolledFrame):
class LoadFlowParametersView(tk.Frame):

def sheet_modified(self, event):
if event.eventname == 'edit_table':
row = event.selected.row
column = event.selected.column
new_value = self.sheet[row, column].data
param = self.sheet.get_index_data(row)
lf_parameters = self.context.lf_parameters
if param == 'distributedSlack':
lf_parameters.distributed_slack = new_value
elif param == 'balanceType':
lf_parameters.balance_type = BalanceType.__members__[new_value]
elif param == 'voltageInitMode':
lf_parameters.voltage_init_mode = VoltageInitMode.__members__[new_value]
elif param == 'readSlackBus':
lf_parameters.read_slack_bus = new_value
elif param == 'writeSlackBus':
lf_parameters.write_slack_bus = new_value
elif param == 'useReactiveLimits':
lf_parameters.use_reactive_limits = new_value
elif param == 'phaseShifterRegulationOn':
lf_parameters.phase_shifter_regulation_on = new_value
elif param == 'transformerVoltageControlOn':
lf_parameters.transformer_voltage_control_on = new_value
elif param == 'shuntCompensatorVoltageControlOn':
lf_parameters.shunt_compensator_voltage_control_on = new_value
elif param == 'connectedComponentMode':
lf_parameters.connected_component_mode = ConnectedComponentMode.__members__[new_value]
elif param == 'twtSplitShuntAdmittance':
lf_parameters.twt_split_shunt_admittance = new_value
elif param == 'dcUseTransformerRatio':
lf_parameters.dc_use_transformer_ratio = new_value
elif param == 'dcPowerFactor':
lf_parameters.dc_power_factor = new_value
else:
new_value = str(new_value)
lf_parameters.provider_parameters[param] = str(new_value)
logging.info(f'Load Flow Parameter "{param}" set to {new_value}')
logging.info(f'Load Flow Parameters: {lf_parameters}')

def __init__(self, parent, context: AppContext, *args, **kwargs):
VerticalScrolledFrame.__init__(self, parent, *args, **kwargs)
tk.Frame.__init__(self, parent, *args, **kwargs)
self.sheet = tks.Sheet(self)
self.sheet.enable_bindings()
self.sheet.bind("<<SheetModified>>", self.sheet_modified)
self.context = context
self.variables = []

i_row = -1
i_row = 0
self.sheet[i_row, 0].data = 'Enable distributed slack'
self.sheet[i_row, 1].checkbox(checked=self.context.lf_parameters.distributed_slack)
self.sheet.set_index_data(r=i_row, value='distributedSlack')

i_row += 1
self.sheet[i_row, 0].data = 'Slack distribution balance type'
self.sheet[i_row, 1].dropdown(
values=[BalanceType.PROPORTIONAL_TO_GENERATION_P.name,
BalanceType.PROPORTIONAL_TO_GENERATION_P_MAX.name,
BalanceType.PROPORTIONAL_TO_GENERATION_PARTICIPATION_FACTOR.name,
BalanceType.PROPORTIONAL_TO_GENERATION_REMAINING_MARGIN.name,
BalanceType.PROPORTIONAL_TO_LOAD.name,
BalanceType.PROPORTIONAL_TO_CONFORM_LOAD.name],
set_value=self.context.lf_parameters.balance_type.name
)
self.sheet.set_index_data(r=i_row, value='balanceType')

i_row += 1
self.sheet[i_row, 0].data = 'Voltage Initialization Mode'
self.sheet[i_row, 1].dropdown(
values=[VoltageInitMode.UNIFORM_VALUES.name,
VoltageInitMode.DC_VALUES.name,
VoltageInitMode.PREVIOUS_VALUES.name],
set_value=self.context.lf_parameters.voltage_init_mode.name
)
self.sheet.set_index_data(r=i_row, value='voltageInitMode')

i_row += 1
self.sheet[i_row, 0].data = 'Read slack bus'
self.sheet[i_row, 1].checkbox(checked=self.context.lf_parameters.read_slack_bus)
self.sheet.set_index_data(r=i_row, value='readSlackBus')

i_row += 1
self.sheet[i_row, 0].data = 'Write slack bus'
self.sheet[i_row, 1].checkbox(checked=self.context.lf_parameters.write_slack_bus)
self.sheet.set_index_data(r=i_row, value='writeSlackBus')

i_row += 1
self.sheet[i_row, 0].data = 'Use reactive limits'
self.sheet[i_row, 1].checkbox(checked=self.context.lf_parameters.use_reactive_limits)
self.sheet.set_index_data(r=i_row, value='useReactiveLimits')

i_row += 1
self.sheet[i_row, 0].data = 'Enable Phase Shifter control'
self.sheet[i_row, 1].checkbox(checked=self.context.lf_parameters.phase_shifter_regulation_on)
self.sheet.set_index_data(r=i_row, value='phaseShifterRegulationOn')

i_row += 1
self.sheet[i_row, 0].data = 'Enable Transformer Voltage control'
self.sheet[i_row, 1].checkbox(checked=self.context.lf_parameters.transformer_voltage_control_on)
self.sheet.set_index_data(r=i_row, value='transformerVoltageControlOn')

i_row += 1
self.sheet[i_row, 0].data = 'Enable Shunt Compensator Voltage control'
self.sheet[i_row, 1].checkbox(checked=self.context.lf_parameters.shunt_compensator_voltage_control_on)
self.sheet.set_index_data(r=i_row, value='shuntCompensatorVoltageControlOn')

i_row += 1
self.sheet[i_row, 0].data = 'Connected component mode'
self.sheet[i_row, 1].dropdown(
values=[ConnectedComponentMode.MAIN.name,
ConnectedComponentMode.ALL.name],
set_value=self.context.lf_parameters.connected_component_mode.name
)
self.sheet.set_index_data(r=i_row, value='connectedComponentMode')

i_row += 1
self.sheet[i_row, 0].data = 'Split transformers shunt admittance'
self.sheet[i_row, 1].checkbox(checked=self.context.lf_parameters.twt_split_shunt_admittance)
self.sheet.set_index_data(r=i_row, value='twtSplitShuntAdmittance')

i_row += 1
self.sheet[i_row, 0].data = 'Ratio of transformers should be used in the flow equations in a DC power flow'
self.sheet[i_row, 1].checkbox(checked=self.context.lf_parameters.dc_use_transformer_ratio)
self.sheet.set_index_data(r=i_row, value='dcUseTransformerRatio')

i_row += 1
self.sheet[
i_row, 0].data = 'Power factor used to convert current limits into active power limits in DC calculations'
self.sheet[i_row, 1].data = self.context.lf_parameters.dc_power_factor
self.sheet.set_index_data(r=i_row, value='dcPowerFactor')
self.sheet.format_cell(i_row, 1, formatter_options=tks.float_formatter(decimals=5))

for param_idx, param_s in lf.get_provider_parameters().iterrows():
i_col = -1
Expand All @@ -40,82 +163,42 @@ def __init__(self, parent, context: AppContext, *args, **kwargs):
if param_s.possible_values and param_s.possible_values != '[]':
param_possible_values = param_s.possible_values[1:-1].split(', ')

name_label = tk.Label(self.interior, text=param_name)
i_col += 1
name_label.grid(row=i_row, column=i_col, sticky=tk.E, padx=10)
itooltip.Hovertip(name_label, '\n'.join(textwrap.wrap(param_description)), hover_delay=100)
self.sheet[i_row, i_col].data = '\n'.join(textwrap.wrap(param_description))
self.sheet.set_index_data(r=i_row, value=param_name)

i_col += 1
if param_type == 'BOOLEAN':
var = tk.IntVar()
self.variables.append(var)
init_val = 0
if param_default == 'true':
init_val = 1
var.set(init_val)
check = ttk.Checkbutton(self.interior, variable=var, onvalue=1, offvalue=0, command=lambda k=param_name, v=var: self.value_update(k, v))
check.grid(row=i_row, column=i_col, sticky=tk.W)
self.sheet[i_row, i_col].checkbox(checked=param_default.lower() == 'true')
elif param_type == 'STRING':
var = tk.StringVar()
self.variables.append(var)
var.set(param_default)
var.trace_add("write", callback=lambda _1, _2, _3, k=param_name, v=var: self.value_update(k, v))
if param_possible_values:
widget = ttk.Combobox(self.interior, textvariable=var, state='readonly', values=param_possible_values)
self.sheet[i_row, i_col].dropdown(
values=param_possible_values,
set_value=param_default,
)
else:
widget = ttk.Entry(self.interior, textvariable=var)
widget.grid(row=i_row, column=i_col, sticky=tk.W+tk.E)
self.sheet[i_row, i_col].data = param_default
elif param_type == 'STRING_LIST':
if param_possible_values:
# FIXME: possibility of reordering (voltageTargetPriorities)
list_box = tk.Listbox(self.interior, selectmode=tk.MULTIPLE, exportselection=False)
i = -1
for p in param_possible_values:
i += 1
list_box.insert(tk.END, p)
if p in param_default:
list_box.selection_set(i)
list_box.bind('<<ListboxSelect>>', func=lambda event, k=param_name: self.list_box_update(event, k))
list_box.grid(row=i_row, column=i_col, sticky=tk.W+tk.E)
self.sheet[i_row, i_col].dropdown(
values=param_possible_values,
set_value=param_default,
)
else:
var = tk.StringVar()
self.variables.append(var)
var.set(param_default)
var.trace_add("write", callback=lambda _1, _2, _3, k=param_name, v=var: self.value_update(k, v))
entry = ttk.Entry(self.interior, textvariable=var)
entry.grid(row=i_row, column=i_col, sticky=tk.W+tk.E)
elif param_type == 'INTEGER' or param_type == 'DOUBLE':
var = tk.StringVar()
self.variables.append(var)
var.set(param_default)
var.trace_add("write", callback=lambda _1, _2, _3, k=param_name, v=var: self.value_update(k, v))
entry = ttk.Entry(self.interior, textvariable=var)
entry.grid(row=i_row, column=i_col, sticky=tk.W)

self.interior.columnconfigure(0)
self.interior.columnconfigure(1, minsize=300)

def value_update(self, k: str, v):
value = v.get()
if isinstance(v, tk.IntVar):
if value:
value = 'true'
else:
value = 'false'
if value:
self.context.lf_parameters.provider_parameters[k] = value
logging.info(f'Load Flow Parameter "{k}" set to {value}')

def list_box_update(self, event, k):
updated_widget = event.widget
selected_indexes = list(event.widget.curselection())
all_items = updated_widget.get(0, tk.END)
selected_items = []
for i in selected_indexes:
selected_items.append(all_items[i])
value = ','.join(selected_items)
self.context.lf_parameters.provider_parameters[k] = value
logging.info(f'Load Flow Parameter "{k}" set to {value}')
self.sheet[i_row, i_col].data = ''
elif param_type == 'INTEGER':
self.sheet[i_row, i_col].data = param_default
self.sheet.format_cell(i_row, i_col, formatter_options=tks.int_formatter())
elif param_type == 'DOUBLE':
self.sheet[i_row, i_col].data = param_default
self.sheet.format_cell(i_row, i_col, formatter_options=tks.float_formatter(decimals=5))

self.sheet.set_header_data(c=0, value="Description")
self.sheet["A"].readonly(readonly=True)
self.sheet.set_header_data(c=1, value="Value")
self.sheet.set_all_cell_sizes_to_text()
self.sheet.set_index_width(300)
self.sheet.pack(fill="both", expand=True)


if __name__ == "__main__":
Expand Down

0 comments on commit 43279fc

Please sign in to comment.