# 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 https://mozilla.org/MPL/2.0/.
# SPDX-License-Identifier: MPL-2.0
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
import matplotlib.colors as plt_colors
from VeraGridEngine.Simulations.results_table import ResultsTable
from VeraGridEngine.Simulations.results_template import ResultsTemplate, ResultsProperty
from VeraGridEngine.basic_structures import IntVec, Vec, StrVec, CxVec
from VeraGridEngine.enumerations import StudyResultsType, ResultTypes, DeviceType
[docs]
class OptimalPowerFlowResults(ResultsTemplate):
LOCAL_RESULTS_DECLARATIONS = (
ResultsProperty(name='bus_names', tpe=StrVec, old_names=list(), expandable=False),
ResultsProperty(name='branch_names', tpe=StrVec, old_names=list(), expandable=False),
ResultsProperty(name='load_names', tpe=StrVec, old_names=list(), expandable=False),
ResultsProperty(name='generator_names', tpe=StrVec, old_names=list(), expandable=False),
ResultsProperty(name='shunt_like_names', tpe=StrVec, old_names=list(), expandable=False),
ResultsProperty(name='battery_names', tpe=StrVec, old_names=list(), expandable=False),
ResultsProperty(name='hvdc_names', tpe=StrVec, old_names=list(), expandable=False),
ResultsProperty(name='vsc_names', tpe=StrVec, old_names=list(), expandable=False),
ResultsProperty(name='fluid_node_names', tpe=StrVec, old_names=list(), expandable=False),
ResultsProperty(name='fluid_path_names', tpe=StrVec, old_names=list(), expandable=False),
ResultsProperty(name='fluid_inj_names', tpe=StrVec, old_names=list(), expandable=False),
ResultsProperty(name='bus_types', tpe=IntVec, old_names=list(), expandable=False),
ResultsProperty(name='voltage', tpe=CxVec, old_names=list(), expandable=False),
ResultsProperty(name='Sbus', tpe=CxVec, old_names=list(), expandable=False),
ResultsProperty(name='bus_shadow_prices', tpe=Vec, old_names=list(), expandable=False),
ResultsProperty(name='load_power', tpe=Vec, old_names=list(), expandable=False),
ResultsProperty(name='load_shedding', tpe=Vec, old_names=list(), expandable=False),
ResultsProperty(name='load_shedding_cost', tpe=Vec, old_names=list(), expandable=False),
ResultsProperty(name='Sf', tpe=CxVec, old_names=list(), expandable=False),
ResultsProperty(name='St', tpe=CxVec, old_names=list(), expandable=False),
ResultsProperty(name='overloads', tpe=Vec, old_names=list(), expandable=False),
ResultsProperty(name='overloads_cost', tpe=Vec, old_names=list(), expandable=False),
ResultsProperty(name='loading', tpe=Vec, old_names=list(), expandable=False),
ResultsProperty(name='losses', tpe=Vec, old_names=list(), expandable=False),
ResultsProperty(name='tap_angle', tpe=Vec, old_names=list(), expandable=False),
ResultsProperty(name='tap_module', tpe=Vec, old_names=list(), expandable=False),
ResultsProperty(name='rates', tpe=Vec, old_names=list(), expandable=False),
ResultsProperty(name='contingency_rates', tpe=Vec, old_names=list(), expandable=False),
ResultsProperty(name='hvdc_Pf', tpe=Vec, old_names=list(), expandable=False),
ResultsProperty(name='hvdc_loading', tpe=Vec, old_names=list(), expandable=False),
ResultsProperty(name='hvdc_losses', tpe=Vec, old_names=list(), expandable=False),
ResultsProperty(name='vsc_Pf', tpe=Vec, old_names=list(), expandable=False),
ResultsProperty(name='vsc_loading', tpe=Vec, old_names=list(), expandable=False),
ResultsProperty(name='vsc_losses', tpe=Vec, old_names=list(), expandable=False),
ResultsProperty(name='generator_power', tpe=Vec, old_names=list(), expandable=False),
ResultsProperty(name='generator_reactive_power', tpe=Vec, old_names=list(), expandable=False),
ResultsProperty(name='generator_shedding', tpe=Vec, old_names=list(), expandable=False),
ResultsProperty(name='battery_power', tpe=Vec, old_names=list(), expandable=False),
ResultsProperty(name='shunt_like_reactive_power', tpe=Vec, old_names=list(), expandable=False),
ResultsProperty(name='fluid_node_p2x_flow', tpe=Vec, old_names=list(), expandable=False),
ResultsProperty(name='fluid_node_current_level', tpe=Vec, old_names=list(), expandable=False),
ResultsProperty(name='fluid_node_spillage', tpe=Vec, old_names=list(), expandable=False),
ResultsProperty(name='fluid_node_flow_in', tpe=Vec, old_names=list(), expandable=False),
ResultsProperty(name='fluid_node_flow_out', tpe=Vec, old_names=list(), expandable=False),
ResultsProperty(name='fluid_path_flow', tpe=Vec, old_names=list(), expandable=False),
ResultsProperty(name='fluid_injection_flow', tpe=Vec, old_names=list(), expandable=False),
ResultsProperty(name='non_linear', tpe=bool, old_names=list(), expandable=False),
ResultsProperty(name='converged', tpe=bool, old_names=list(), expandable=False),
ResultsProperty(name='error', tpe=float, old_names=list(), expandable=False),
ResultsProperty(name='contingency_flows_list', tpe=list, old_names=list(), expandable=False),
ResultsProperty(name='contingency_indices_list', tpe=list, old_names=list(), expandable=False),
ResultsProperty(name='contingency_flows_slacks_list', tpe=list, old_names=list(), expandable=False),
ResultsProperty(name='F', tpe=IntVec, old_names=list(), expandable=False),
ResultsProperty(name='T', tpe=IntVec, old_names=list(), expandable=False),
ResultsProperty(name='hvdc_F', tpe=IntVec, old_names=list(), expandable=False),
ResultsProperty(name='hvdc_T', tpe=IntVec, old_names=list(), expandable=False),
ResultsProperty(name='bus_area_indices', tpe=IntVec, old_names=list(), expandable=False),
ResultsProperty(name='area_names', tpe=IntVec, old_names=list(), expandable=False),
)
__slots__ = (
"bus_names",
"branch_names",
"load_names",
"generator_names",
"battery_names",
"shunt_like_names",
"hvdc_names",
"vsc_names",
"fluid_node_names",
"fluid_path_names",
"fluid_inj_names",
"bus_types",
"voltage",
"Sbus",
"bus_shadow_prices",
"load_power",
"load_shedding",
"load_shedding_cost",
"Sf",
"St",
"overloads",
"overloads_cost",
"loading",
"losses",
"tap_angle",
"tap_module",
"rates",
"contingency_rates",
"hvdc_Pf",
"hvdc_loading",
"hvdc_losses",
"vsc_Pf",
"vsc_loading",
"vsc_losses",
"generator_shedding",
"generator_power",
"generator_reactive_power",
"shunt_like_reactive_power",
"battery_power",
"fluid_node_p2x_flow",
"fluid_node_current_level",
"fluid_node_spillage",
"fluid_node_flow_in",
"fluid_node_flow_out",
"fluid_path_flow",
"fluid_injection_flow",
"contingency_flows_list",
"contingency_indices_list",
"contingency_flows_slacks_list",
"non_linear",
"converged",
"error",
"plot_bars_limit",
)
def __init__(self,
bus_names: StrVec,
branch_names: StrVec,
load_names: StrVec,
generator_names: StrVec,
shunt_like_names: StrVec,
battery_names: StrVec,
hvdc_names: StrVec,
vsc_names: StrVec,
bus_types: IntVec,
area_names: StrVec,
fluid_node_names: StrVec,
fluid_path_names: StrVec,
fluid_inj_names: StrVec,
F: IntVec,
T: IntVec,
F_hvdc: IntVec,
T_hvdc: IntVec,
bus_area_indices: IntVec):
"""
Constructor
:param bus_names:
:param branch_names:
:param load_names:
:param generator_names:
:param battery_names:
:param hvdc_names:
:param bus_types:
:param area_names:
:param F:
:param T:
:param F_hvdc:
:param T_hvdc:
:param bus_area_indices:
"""
ResultsTemplate.__init__(self,
name='OPF',
available_results={ResultTypes.BusResults: [ResultTypes.BusVoltageModule,
ResultTypes.BusVoltageAngle,
ResultTypes.BusShadowPrices,
ResultTypes.BusActivePower,
ResultTypes.BusReactivePower],
ResultTypes.GeneratorResults: [ResultTypes.GeneratorPower,
ResultTypes.GeneratorReactivePower,
ResultTypes.GeneratorShedding],
ResultTypes.ShuntResults: [ResultTypes.ShuntReactivePower],
ResultTypes.BatteryResults: [ResultTypes.BatteryPower],
ResultTypes.LoadResults: [ResultTypes.LoadPower,
ResultTypes.LoadShedding,
ResultTypes.LoadSheddingCost],
ResultTypes.BranchResults: [ResultTypes.BranchActivePowerFrom,
ResultTypes.BranchActivePowerTo,
ResultTypes.BranchLoading,
ResultTypes.BranchLosses,
ResultTypes.BranchOverloads,
ResultTypes.BranchOverloadsCost,
ResultTypes.BranchTapAngle,
ResultTypes.BranchTapModule],
ResultTypes.HvdcResults: [ResultTypes.HvdcPowerFrom,
ResultTypes.HvdcLoading],
ResultTypes.VscResults: [ResultTypes.VscPowerFromPositive,
ResultTypes.VscLoading],
ResultTypes.ReportsResults: [ResultTypes.ContingencyFlowsReport],
ResultTypes.AreaResults: [ResultTypes.InterAreaExchange,
ResultTypes.ActivePowerFlowPerArea,
ResultTypes.LossesPerArea,
ResultTypes.LossesPercentPerArea,
ResultTypes.LossesPerGenPerArea],
ResultTypes.SpecialPlots: [
ResultTypes.BusVoltagePolarPlot
]
},
time_array=None,
clustering_results=None,
study_results_type=StudyResultsType.OptimalPowerFlow)
n = len(bus_names)
m = len(branch_names)
ngen = len(generator_names)
nbat = len(battery_names)
nsh = len(shunt_like_names)
nload = len(load_names)
nhvdc = len(hvdc_names)
nvsc = len(vsc_names)
n_fluid_node = len(fluid_node_names)
n_fluid_path = len(fluid_path_names)
n_fluid_inj = len(fluid_inj_names)
self.bus_names = bus_names
self.branch_names = branch_names
self.load_names = load_names
self.generator_names = generator_names
self.battery_names = battery_names
self.shunt_like_names = shunt_like_names
self.hvdc_names = hvdc_names
self.vsc_names = vsc_names
self.fluid_node_names = fluid_node_names
self.fluid_path_names = fluid_path_names
self.fluid_inj_names = fluid_inj_names
self.bus_types = bus_types
self.voltage = np.zeros(n, dtype=complex)
self.Sbus = np.zeros(n, dtype=complex)
self.bus_shadow_prices = np.zeros(n, dtype=float)
self.load_power = np.zeros(nload, dtype=float)
self.load_shedding = np.zeros(nload, dtype=float)
self.load_shedding_cost = np.zeros(nload, dtype=float)
self.Sf = np.zeros(m, dtype=float)
self.St = np.zeros(m, dtype=float)
self.overloads = np.zeros(m, dtype=float)
self.overloads_cost = np.zeros(m, dtype=float)
self.loading = np.zeros(m, dtype=float)
self.losses = np.zeros(m, dtype=float)
self.tap_angle = np.zeros(m, dtype=float)
self.tap_module = np.ones(m, dtype=float)
self.rates = np.zeros(m, dtype=float)
self.contingency_rates = np.zeros(m, dtype=float)
self.hvdc_Pf = np.zeros(nhvdc, dtype=float)
self.hvdc_loading = np.zeros(nhvdc, dtype=float)
self.hvdc_losses = np.zeros(nhvdc, dtype=float)
self.vsc_Pf = np.zeros(nvsc, dtype=float)
self.vsc_loading = np.zeros(nvsc, dtype=float)
self.vsc_losses = np.zeros(nvsc, dtype=float)
self.generator_shedding = np.zeros(ngen, dtype=float)
self.generator_power = np.zeros(ngen, dtype=float)
self.generator_reactive_power = np.zeros(ngen, dtype=float)
self.shunt_like_reactive_power = np.zeros(nsh, dtype=float)
self.battery_power = np.zeros(nbat, dtype=float)
self.fluid_node_p2x_flow = np.zeros(n_fluid_node, dtype=float) # m3
self.fluid_node_current_level = np.zeros(n_fluid_node, dtype=float) # m3
self.fluid_node_spillage = np.zeros(n_fluid_node, dtype=float) # m3/s
self.fluid_node_flow_in = np.zeros(n_fluid_node, dtype=float) # m3/s
self.fluid_node_flow_out = np.zeros(n_fluid_node, dtype=float) # m3/s
self.fluid_path_flow = np.zeros(n_fluid_path, dtype=float) # m3/s
self.fluid_injection_flow = np.zeros(n_fluid_inj, dtype=float) # m3/s
self.contingency_flows_list = list()
self.contingency_indices_list = list() # [(t, m, c), ...]
self.contingency_flows_slacks_list = list()
self.non_linear = False
self.converged = False
self.error = 0.0
# vars for the inter-area computation
self.F = F
self.T = T
self.hvdc_F = F_hvdc
self.hvdc_T = T_hvdc
self.bus_area_indices = bus_area_indices
self.area_names = area_names
self.plot_bars_limit = 100
@property
def phase_shift(self) -> Vec:
"""
Cover for old API
:return: tap angles in rad
"""
return self.tap_angle
[docs]
def get_bus_df(self) -> pd.DataFrame:
"""
Get a DataFrame with the buses results
:return: DataFrame
"""
if self.non_linear:
return pd.DataFrame(data={'Vm': np.abs(self.voltage),
'Va': np.angle(self.voltage, deg=True),
'P': self.Sbus.real,
'Q': self.Sbus.imag,
'Shadow price': self.bus_shadow_prices},
index=self.bus_names)
else:
return pd.DataFrame(data={'Va': np.angle(self.voltage, deg=True),
'P': self.Sbus.real,
'Shadow price': self.bus_shadow_prices},
index=self.bus_names)
[docs]
def get_branch_df(self) -> pd.DataFrame:
"""
Get a DataFrame with the branches results
:return: DataFrame
"""
if self.non_linear:
return pd.DataFrame(data={'Pf': self.Sf.real,
'Pt': self.St.real,
'Qf': self.Sf.imag,
'Qt': self.St.imag,
'Tap angle': self.tap_angle,
'loading': self.loading.real * 100.0},
index=self.branch_names)
else:
return pd.DataFrame(data={'Pf': self.Sf.real,
'Pt': self.St.real,
'Tap angle': self.tap_angle,
'loading': self.loading.real * 100.0},
index=self.branch_names)
[docs]
def get_gen_df(self) -> pd.DataFrame:
"""
Get a DataFrame with the generator results
:return: DataFrame
"""
if self.non_linear:
return pd.DataFrame(
data={
'P': self.generator_power,
'Q': self.generator_reactive_power,
'P shedding': self.generator_shedding,
},
index=self.generator_names
)
else:
return pd.DataFrame(
data={'P': self.generator_power,
'P shedding': self.generator_shedding},
index=self.generator_names
)
[docs]
def get_batt_df(self) -> pd.DataFrame:
"""
Get a DataFrame with the battery results
:return: DataFrame
"""
if self.non_linear:
return pd.DataFrame(
data={
'P': self.battery_power,
},
index=self.battery_names
)
else:
return pd.DataFrame(data={'P': self.battery_power},
index=self.battery_names)
[docs]
def get_hvdc_df(self) -> pd.DataFrame:
"""
Get a DataFrame with the battery results
:return: DataFrame
"""
return pd.DataFrame(data={'P': self.hvdc_Pf,
'Loading': self.hvdc_loading},
index=self.hvdc_names)
[docs]
def mdl(self, result_type) -> ResultsTable:
"""
Plot the results
:param result_type: type of results (string)
:return: DataFrame of the results (or None if the result was not understood)
"""
if result_type == ResultTypes.BusVoltageModule:
return ResultsTable(data=np.abs(self.voltage),
index=self.bus_names,
idx_device_type=DeviceType.BusDevice,
columns=[result_type.value],
cols_device_type=DeviceType.NoDevice,
title=str(result_type.value),
ylabel='(p.u.)',
xlabel='',
units='(p.u.)')
elif result_type == ResultTypes.BusVoltageAngle:
return ResultsTable(data=np.angle(self.voltage, deg=True),
index=self.bus_names,
idx_device_type=DeviceType.BusDevice,
columns=[result_type.value],
cols_device_type=DeviceType.NoDevice,
title=str(result_type.value),
ylabel='(deg)',
xlabel='',
units='(deg)')
elif result_type == ResultTypes.BusShadowPrices:
return ResultsTable(data=self.bus_shadow_prices,
index=self.bus_names,
idx_device_type=DeviceType.BusDevice,
columns=[result_type.value],
cols_device_type=DeviceType.NoDevice,
title=str(result_type.value),
ylabel='(Currency/MW)',
xlabel='',
units='(Currency/MW)')
elif result_type == ResultTypes.BusActivePower:
return ResultsTable(data=self.Sbus.real,
index=self.bus_names,
idx_device_type=DeviceType.BusDevice,
columns=[result_type.value],
cols_device_type=DeviceType.NoDevice,
title=str(result_type.value),
ylabel='(MW)',
xlabel='',
units='(MW)')
elif result_type == ResultTypes.BusReactivePower:
return ResultsTable(data=self.Sbus.imag,
index=self.bus_names,
idx_device_type=DeviceType.BusDevice,
columns=[result_type.value],
cols_device_type=DeviceType.NoDevice,
title=str(result_type.value),
ylabel='(MVAr)',
xlabel='',
units='(MVAr)')
elif result_type == ResultTypes.BranchActivePowerFrom:
return ResultsTable(data=self.Sf.real,
index=self.branch_names,
idx_device_type=DeviceType.BranchDevice,
columns=[result_type.value],
cols_device_type=DeviceType.NoDevice,
title=str(result_type.value),
ylabel='(MW)',
xlabel='',
units='(MW)')
elif result_type == ResultTypes.BranchActivePowerTo:
return ResultsTable(data=self.St.real,
index=self.branch_names,
idx_device_type=DeviceType.BranchDevice,
columns=[result_type.value],
cols_device_type=DeviceType.NoDevice,
title=str(result_type.value),
ylabel='(MW)',
xlabel='',
units='(MW)')
elif result_type == ResultTypes.BranchLoading:
return ResultsTable(data=self.loading * 100.0,
index=self.branch_names,
idx_device_type=DeviceType.BranchDevice,
columns=[result_type.value],
cols_device_type=DeviceType.NoDevice,
title=str(result_type.value),
ylabel='(%)',
xlabel='',
units='(%)')
elif result_type == ResultTypes.BranchOverloads:
return ResultsTable(data=np.abs(self.overloads),
index=self.branch_names,
idx_device_type=DeviceType.BranchDevice,
columns=[result_type.value],
cols_device_type=DeviceType.NoDevice,
title=str(result_type.value),
ylabel='(MW)',
xlabel='',
units='(MW)')
elif result_type == ResultTypes.BranchOverloadsCost:
return ResultsTable(data=self.overloads_cost,
index=self.branch_names,
idx_device_type=DeviceType.BranchDevice,
columns=[result_type.value],
cols_device_type=DeviceType.NoDevice,
title=str(result_type.value),
ylabel='(Currency)',
xlabel='',
units='(Currency)')
elif result_type == ResultTypes.BranchLosses:
return ResultsTable(data=self.losses.real,
index=self.branch_names,
idx_device_type=DeviceType.BranchDevice,
columns=[result_type.value],
cols_device_type=DeviceType.NoDevice,
title=str(result_type.value),
ylabel='(MW)',
xlabel='',
units='(MW)')
elif result_type == ResultTypes.BranchTapAngle:
return ResultsTable(data=np.rad2deg(self.tap_angle),
index=self.branch_names,
idx_device_type=DeviceType.BranchDevice,
columns=[result_type.value],
cols_device_type=DeviceType.NoDevice,
title=str(result_type.value),
ylabel='(deg)',
xlabel='',
units='(deg)')
elif result_type == ResultTypes.BranchTapModule:
return ResultsTable(data=np.rad2deg(self.tap_module),
index=self.branch_names,
idx_device_type=DeviceType.BranchDevice,
columns=[result_type.value],
cols_device_type=DeviceType.NoDevice,
title=str(result_type.value),
ylabel='(deg)',
xlabel='',
units='(deg)')
elif result_type == ResultTypes.LoadPower:
return ResultsTable(data=self.load_power,
index=self.load_names,
idx_device_type=DeviceType.LoadLikeDevice,
columns=[result_type.value],
cols_device_type=DeviceType.NoDevice,
title=str(result_type.value),
ylabel='(MW)',
xlabel='',
units='(MW)')
elif result_type == ResultTypes.LoadShedding:
return ResultsTable(data=self.load_shedding,
index=self.load_names,
idx_device_type=DeviceType.LoadLikeDevice,
columns=[result_type.value],
cols_device_type=DeviceType.NoDevice,
title=str(result_type.value),
ylabel='(MW)',
xlabel='',
units='(MW)')
elif result_type == ResultTypes.LoadSheddingCost:
return ResultsTable(data=self.load_shedding_cost,
index=self.load_names,
idx_device_type=DeviceType.LoadLikeDevice,
columns=[result_type.value],
cols_device_type=DeviceType.NoDevice,
title=str(result_type.value),
ylabel='(Currency)',
xlabel='',
units='(Currency)')
elif result_type == ResultTypes.GeneratorShedding:
return ResultsTable(data=self.generator_shedding,
index=self.generator_names,
idx_device_type=DeviceType.GeneratorDevice,
columns=[result_type.value],
cols_device_type=DeviceType.NoDevice,
title=str(result_type.value),
ylabel='(MW)',
xlabel='',
units='(MW)')
elif result_type == ResultTypes.GeneratorPower:
return ResultsTable(data=self.generator_power,
index=self.generator_names,
idx_device_type=DeviceType.GeneratorDevice,
columns=[result_type.value],
cols_device_type=DeviceType.NoDevice,
title=str(result_type.value),
ylabel='(MW)',
xlabel='',
units='(MW)')
elif result_type == ResultTypes.GeneratorReactivePower:
return ResultsTable(data=self.generator_reactive_power,
index=self.generator_names,
idx_device_type=DeviceType.GeneratorDevice,
columns=[result_type.value],
cols_device_type=DeviceType.NoDevice,
title=str(result_type.value),
ylabel='(MVAr)',
xlabel='',
units='(MVAr)')
elif result_type == ResultTypes.BatteryPower:
return ResultsTable(data=self.battery_power,
index=self.battery_names,
idx_device_type=DeviceType.BatteryDevice,
columns=[result_type.value],
cols_device_type=DeviceType.NoDevice,
title=str(result_type.value),
ylabel='(MW)',
xlabel='',
units='(MW)')
elif result_type == ResultTypes.ShuntReactivePower:
return ResultsTable(data=self.shunt_like_reactive_power,
index=self.shunt_like_names,
idx_device_type=DeviceType.ShuntLikeDevice,
columns=[result_type.value],
cols_device_type=DeviceType.NoDevice,
title=str(result_type.value),
ylabel='(MVAr)',
xlabel='',
units='(MVAr)')
elif result_type == ResultTypes.HvdcPowerFrom:
return ResultsTable(data=self.hvdc_Pf,
index=self.hvdc_names,
idx_device_type=DeviceType.HVDCLineDevice,
columns=[result_type.value],
cols_device_type=DeviceType.NoDevice,
title=str(result_type.value),
ylabel='(MW)',
xlabel='',
units='(MW)')
elif result_type == ResultTypes.HvdcLoading:
return ResultsTable(data=self.hvdc_loading * 100.0,
index=self.hvdc_names,
idx_device_type=DeviceType.HVDCLineDevice,
columns=[result_type.value],
cols_device_type=DeviceType.NoDevice,
title=str(result_type.value),
ylabel='(%)',
xlabel='',
units='(%)')
elif result_type == ResultTypes.VscPowerFromPositive:
return ResultsTable(data=self.vsc_Pf,
index=self.vsc_names,
idx_device_type=DeviceType.VscDevice,
columns=[result_type.value],
cols_device_type=DeviceType.NoDevice,
title=str(result_type.value),
ylabel='(MW)',
xlabel='',
units='(MW)')
elif result_type == ResultTypes.VscLoading:
return ResultsTable(data=self.vsc_loading * 100.0,
index=self.vsc_names,
idx_device_type=DeviceType.VscDevice,
columns=[result_type.value],
cols_device_type=DeviceType.NoDevice,
title=str(result_type.value),
ylabel='(%)',
xlabel='',
units='(%)')
elif result_type == ResultTypes.ContingencyFlowsReport:
y = list()
index = list()
for i in range(len(self.contingency_flows_list)):
if self.contingency_flows_list[i] != 0.0:
m, c = self.contingency_indices_list[i]
y.append((m, c,
self.branch_names[m], self.branch_names[c],
self.contingency_flows_list[i], self.Sf[m],
self.contingency_flows_list[i] / self.contingency_rates[c] * 100,
self.Sf[m] / self.rates[m] * 100))
index.append(i)
columns = ['Monitored idx ', 'Contingency idx',
'Monitored', 'Contingency',
'ContingencyFlow (MW)', 'Base flow (MW)',
'ContingencyFlow (%)', 'Base flow (%)']
return ResultsTable(data=np.array(y, dtype=object),
index=index,
idx_device_type=DeviceType.NoDevice,
columns=columns,
cols_device_type=DeviceType.NoDevice,
title=str(result_type.value))
elif result_type == ResultTypes.InterAreaExchange:
index = [a + '->' for a in self.area_names]
columns = ['->' + a for a in self.area_names]
y = self.get_inter_area_flows(area_names=self.area_names,
F=self.F,
T=self.T,
Sf=self.Sf,
hvdc_F=self.hvdc_F,
hvdc_T=self.hvdc_T,
hvdc_Pf=self.hvdc_Pf,
bus_area_indices=self.bus_area_indices).real
return ResultsTable(data=np.array(y, dtype=object),
index=index,
idx_device_type=DeviceType.AreaDevice,
columns=columns,
cols_device_type=DeviceType.AreaDevice,
title=str(result_type.value),
units='(MW)')
elif result_type == ResultTypes.LossesPercentPerArea:
index = [a + '->' for a in self.area_names]
columns = ['->' + a for a in self.area_names]
Pf = self.get_branch_values_per_area(np.abs(self.Sf.real), self.area_names,
self.bus_area_indices, self.F, self.T)
Pf += self.get_hvdc_values_per_area(np.abs(self.hvdc_Pf), self.area_names, self.bus_area_indices,
self.hvdc_F, self.hvdc_T)
Pl = self.get_branch_values_per_area(np.abs(self.losses.real), self.area_names, self.bus_area_indices,
self.F, self.T)
# Pl += self.get_hvdc_values_per_area(np.abs(self.hvdc_losses))
y = Pl / (Pf + 1e-20) * 100.0
return ResultsTable(data=np.array(y, dtype=object),
index=index,
idx_device_type=DeviceType.AreaDevice,
columns=columns,
cols_device_type=DeviceType.AreaDevice,
title=str(result_type.value),
units='(%)')
elif result_type == ResultTypes.LossesPerGenPerArea:
index = [a for a in self.area_names]
columns = [result_type.value]
gen_bus = self.Sbus.copy().real
gen_bus[gen_bus < 0] = 0
Gf = self.get_bus_values_per_area(gen_bus, self.area_names, self.bus_area_indices)
Pl = self.get_branch_values_per_area(np.abs(self.losses.real), self.area_names, self.bus_area_indices,
self.F, self.T)
Pl += self.get_hvdc_values_per_area(np.abs(self.hvdc_losses), self.area_names, self.bus_area_indices,
self.hvdc_F, self.hvdc_T)
y = np.zeros(len(self.area_names))
for i in range(len(self.area_names)):
y[i] = Pl[i, i] / (Gf[i] + 1e-20) * 100.0
return ResultsTable(data=np.array(y, dtype=object),
index=index,
idx_device_type=DeviceType.AreaDevice,
columns=columns,
cols_device_type=DeviceType.NoDevice,
title=str(result_type.value),
units='(%)')
elif result_type == ResultTypes.LossesPerArea:
index = [a + '->' for a in self.area_names]
columns = ['->' + a for a in self.area_names]
y = self.get_branch_values_per_area(np.abs(self.losses.real), self.area_names, self.bus_area_indices,
self.F, self.T)
y += self.get_hvdc_values_per_area(np.abs(self.hvdc_losses), self.area_names, self.bus_area_indices,
self.hvdc_F, self.hvdc_T)
return ResultsTable(data=np.array(y, dtype=object),
index=index,
idx_device_type=DeviceType.AreaDevice,
columns=columns,
cols_device_type=DeviceType.AreaDevice,
title=str(result_type.value),
units='(%)')
elif result_type == ResultTypes.ActivePowerFlowPerArea:
index = [a + '->' for a in self.area_names]
columns = ['->' + a for a in self.area_names]
y = self.get_branch_values_per_area(np.abs(self.Sf.real), self.area_names, self.bus_area_indices,
self.F, self.T)
y += self.get_hvdc_values_per_area(np.abs(self.hvdc_Pf), self.area_names, self.bus_area_indices,
self.hvdc_F, self.hvdc_T)
return ResultsTable(data=np.array(y, dtype=object),
index=index,
idx_device_type=DeviceType.AreaDevice,
columns=columns,
cols_device_type=DeviceType.AreaDevice,
title=str(result_type.value),
units='(MW)')
elif result_type == ResultTypes.BusVoltagePolarPlot:
vm = np.abs(self.voltage)
va = np.angle(self.voltage, deg=True)
va_rad = np.angle(self.voltage, deg=False)
data = np.c_[vm, va]
if self.plotting_allowed():
plt.ion()
color_norm = plt_colors.LogNorm()
fig = plt.figure(figsize=(8, 6))
ax3 = plt.subplot(1, 1, 1, projection='polar')
sc3 = ax3.scatter(va_rad, vm, c=vm, norm=color_norm)
fig.suptitle(result_type.value)
plt.tight_layout()
plt.show()
return ResultsTable(data=data,
index=self.bus_names,
idx_device_type=DeviceType.BusDevice,
columns=np.array(['Voltage module', 'Voltage angle (deg)']),
cols_device_type=DeviceType.NoDevice,
title=result_type.value,
ylabel='(p.u., deg)',
units='(p.u., deg)')
else:
raise Exception('Result type not understood:' + str(result_type))