Source code for VeraGridEngine.Devices.Branches.upfc

# 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

from typing import Tuple

import pandas as pd
import numpy as np
from matplotlib import pyplot as plt

from VeraGridEngine.Devices.Substation.bus import Bus
from VeraGridEngine.enumerations import BuildStatus, PrpCat
from VeraGridEngine.Devices.Parents.branch_parent import BranchParent
from VeraGridEngine.Devices.Parents.editable_device import DeviceType, GCProp


[docs] class UPFC(BranchParent): __slots__ = ( '_R', '_X', '_Rsh', '_Xsh', '_R0', '_X0', '_Rsh0', '_Xsh0', '_R2', '_X2', '_Rsh2', '_Xsh2', '_Vsh', '_Pfset', '_Qfset', ) LOCAL_PROPERTY_DECLARATIONS: Tuple[GCProp, ...] = ( GCProp( prop_name='R', units='p.u.', tpe=float, definition='Series positive sequence resistance.', old_names=['Rs'], cat=[PrpCat.PF], ), GCProp( prop_name='X', units='p.u.', tpe=float, definition='Series positive sequence reactance.', old_names=['Xs'], cat=[PrpCat.PF], ), GCProp( prop_name='Rsh', units='p.u.', tpe=float, definition='Shunt positive sequence resistance.', cat=[PrpCat.PF], ), GCProp( prop_name='Xsh', units='p.u.', tpe=float, definition='Shunt positive sequence resistance.', cat=[PrpCat.PF], ), GCProp( prop_name='R0', units='p.u.', tpe=float, definition='Series zero sequence resistance.', old_names=['Rs0'], cat=[PrpCat.SC, PrpCat.PF3], ), GCProp( prop_name='X0', units='p.u.', tpe=float, definition='Series zero sequence reactance.', old_names=['Xs0'], cat=[PrpCat.SC, PrpCat.PF3], ), GCProp( prop_name='Rsh0', units='p.u.', tpe=float, definition='Shunt zero sequence resistance.', cat=[PrpCat.SC, PrpCat.PF3], ), GCProp( prop_name='Xsh0', units='p.u.', tpe=float, definition='Shunt zero sequence resistance.', cat=[PrpCat.SC, PrpCat.PF3], ), GCProp( prop_name='R2', units='p.u.', tpe=float, definition='Series negative sequence resistance.', old_names=['Rs2'], cat=[PrpCat.SC, PrpCat.PF3], ), GCProp( prop_name='X2', units='p.u.', tpe=float, definition='Series negative sequence reactance.', old_names=['Xs2'], cat=[PrpCat.SC, PrpCat.PF3], ), GCProp( prop_name='Rsh2', units='p.u.', tpe=float, definition='Shunt negative sequence resistance.', cat=[PrpCat.SC, PrpCat.PF3], ), GCProp( prop_name='Xsh2', units='p.u.', tpe=float, definition='Shunt negative sequence resistance.', cat=[PrpCat.SC, PrpCat.PF3], ), GCProp( prop_name='Vsh', units='p.u.', tpe=float, definition='Shunt voltage set point.', cat=[PrpCat.PF], ), GCProp( prop_name='Pfset', units='MW', tpe=float, definition='Active power set point.', cat=[PrpCat.PF], ), GCProp( prop_name='Qfset', units='MVAr', tpe=float, definition='Active power set point.', cat=[PrpCat.PF], ), ) def __init__(self, bus_from: Bus = None, bus_to: Bus = None, name='UPFC', code='', idtag=None, active=True, rs=0.0, xs=0.00001, rp=0.0, xp=0.0, vp=1.0, Pset=0.0, Qset=0.0, design_rate: float = 9999, rate=9999, mttf=0, mttr=0, cost=100, contingency_factor=1.0, protection_rating_factor: float = 1.4, contingency_enabled=True, monitor_loading=True, rs0=0.0, xs0=0.00001, rp0=0.0, xp0=0.0, rs2=0.0, xs2=0.00001, rp2=0.0, xp2=0.0, capex=0, opex=0, build_status: BuildStatus = BuildStatus.Commissioned): """ Unified Power Flow Converter (UPFC) :param bus_from: :param bus_to: :param name: :param code: :param idtag: :param active: :param rs: series resistance (p.u.) :param xs: series reactance (p.u.) :param rp: shunt resistance (p.u.) :param xp: shunt reactance (p.u.) :param vp: shunt voltage set point (p.u.) :param Pset: Power set point (MW) :param Qset: :param design_rate: Design rate (MVA) :param rate: Power rating (MVA) :param mttf: :param mttr: :param cost: :param contingency_factor: :param contingency_enabled: :param monitor_loading: :param rs0: :param xs0: :param rp0: :param xp0: :param rs2: :param xs2: :param rp2: :param xp2: :param capex: :param opex: :param build_status: """ BranchParent.__init__(self, name=name, idtag=idtag, code=code, bus_from=bus_from, bus_to=bus_to, active=active, reducible=False, design_rate=design_rate, rate=rate, contingency_factor=contingency_factor, protection_rating_factor=protection_rating_factor, contingency_enabled=contingency_enabled, monitor_loading=monitor_loading, mttf=mttf, mttr=mttr, build_status=build_status, capex=capex, opex=opex, cost=cost, temp_base=25, temp_oper=25, alpha=0.0033, device_type=DeviceType.UpfcDevice) # total impedance and admittance in p.u. self.R = float(rs) self.X = float(xs) self.Rsh = float(rp) self.Xsh = float(xp) self.R0 = float(rs0) self.X0 = float(xs0) self.Rsh0 = float(rp0) self.Xsh0 = float(xp0) self.R2 = float(rs2) self.X2 = float(xs2) self.Rsh2 = float(rp2) self.Xsh2 = float(xp2) self.Vsh = float(vp) self.Pfset = float(Pset) self.Qfset = float(Qset)
[docs] def get_ysh1(self): """ :return: """ return 1.0 / complex(self.Rsh + 1e-20, self.Xsh)
[docs] def get_ysh0(self): """ :return: """ return 1.0 / complex(self.Rsh0 + 1e-20, self.Xsh0)
[docs] def get_ysh2(self): """ :return: """ return 1.0 / complex(self.Rsh2 + 1e-20, self.Xsh2)
[docs] def get_max_bus_nominal_voltage(self): return max(self.bus_from.Vnom, self.bus_to.Vnom)
[docs] def get_min_bus_nominal_voltage(self): return min(self.bus_from.Vnom, self.bus_to.Vnom)
[docs] def change_base(self, Sbase_old: float, Sbase_new: float): """ :param Sbase_old: :param Sbase_new: :return: """ b = Sbase_new / Sbase_old self.R *= b self.X *= b self.Rsh *= b self.X *= b
[docs] def plot_profiles(self, time_series=None, my_index=0, show_fig=True): """ Plot the time series results of this object :param time_series: TimeSeries Instance :param my_index: index of this object in the simulation :param show_fig: Show the figure? """ if time_series is not None: fig = plt.figure(figsize=(12, 8)) ax_1 = fig.add_subplot(211) ax_2 = fig.add_subplot(212, sharex=ax_1) x = time_series.results.time_array # loading y = time_series.results.loading.real * 100.0 df = pd.DataFrame(data=y[:, my_index], index=x, columns=[self.name]) ax_1.set_title('Loading', fontsize=14) ax_1.set_ylabel('Loading [%]', fontsize=11) df.plot(ax=ax_1) # losses y = np.abs(time_series.results.losses) df = pd.DataFrame(data=y[:, my_index], index=x, columns=[self.name]) ax_2.set_title('Losses', fontsize=14) ax_2.set_ylabel('Losses [MVA]', fontsize=11) df.plot(ax=ax_2) plt.legend() fig.suptitle(self.name, fontsize=20) if show_fig: plt.show()
# Scalar property accessors coerce assignments to the declared schema types. @property def R(self) -> float: """ Get ``R``. :return: float """ return self._R @R.setter def R(self, val: float) -> None: """ Set ``R``. :param val: Value to assign. :return: None """ self._R = float(val) @property def X(self) -> float: """ Get ``X``. :return: float """ return self._X @X.setter def X(self, val: float) -> None: """ Set ``X``. :param val: Value to assign. :return: None """ self._X = float(val) @property def Rsh(self) -> float: """ Get ``Rsh``. :return: float """ return self._Rsh @Rsh.setter def Rsh(self, val: float) -> None: """ Set ``Rsh``. :param val: Value to assign. :return: None """ self._Rsh = float(val) @property def Xsh(self) -> float: """ Get ``Xsh``. :return: float """ return self._Xsh @Xsh.setter def Xsh(self, val: float) -> None: """ Set ``Xsh``. :param val: Value to assign. :return: None """ self._Xsh = float(val) @property def R0(self) -> float: """ Get ``R0``. :return: float """ return self._R0 @R0.setter def R0(self, val: float) -> None: """ Set ``R0``. :param val: Value to assign. :return: None """ self._R0 = float(val) @property def X0(self) -> float: """ Get ``X0``. :return: float """ return self._X0 @X0.setter def X0(self, val: float) -> None: """ Set ``X0``. :param val: Value to assign. :return: None """ self._X0 = float(val) @property def Rsh0(self) -> float: """ Get ``Rsh0``. :return: float """ return self._Rsh0 @Rsh0.setter def Rsh0(self, val: float) -> None: """ Set ``Rsh0``. :param val: Value to assign. :return: None """ self._Rsh0 = float(val) @property def Xsh0(self) -> float: """ Get ``Xsh0``. :return: float """ return self._Xsh0 @Xsh0.setter def Xsh0(self, val: float) -> None: """ Set ``Xsh0``. :param val: Value to assign. :return: None """ self._Xsh0 = float(val) @property def R2(self) -> float: """ Get ``R2``. :return: float """ return self._R2 @R2.setter def R2(self, val: float) -> None: """ Set ``R2``. :param val: Value to assign. :return: None """ self._R2 = float(val) @property def X2(self) -> float: """ Get ``X2``. :return: float """ return self._X2 @X2.setter def X2(self, val: float) -> None: """ Set ``X2``. :param val: Value to assign. :return: None """ self._X2 = float(val) @property def Rsh2(self) -> float: """ Get ``Rsh2``. :return: float """ return self._Rsh2 @Rsh2.setter def Rsh2(self, val: float) -> None: """ Set ``Rsh2``. :param val: Value to assign. :return: None """ self._Rsh2 = float(val) @property def Xsh2(self) -> float: """ Get ``Xsh2``. :return: float """ return self._Xsh2 @Xsh2.setter def Xsh2(self, val: float) -> None: """ Set ``Xsh2``. :param val: Value to assign. :return: None """ self._Xsh2 = float(val) @property def Vsh(self) -> float: """ Get ``Vsh``. :return: float """ return self._Vsh @Vsh.setter def Vsh(self, val: float) -> None: """ Set ``Vsh``. :param val: Value to assign. :return: None """ self._Vsh = float(val) @property def Pfset(self) -> float: """ Get ``Pfset``. :return: float """ return self._Pfset @Pfset.setter def Pfset(self, val: float) -> None: """ Set ``Pfset``. :param val: Value to assign. :return: None """ self._Pfset = float(val) @property def Qfset(self) -> float: """ Get ``Qfset``. :return: float """ return self._Qfset @Qfset.setter def Qfset(self, val: float) -> None: """ Set ``Qfset``. :param val: Value to assign. :return: None """ self._Qfset = float(val)