Source code for VeraGridEngine.Simulations.OPF.opf_results

# 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))