Source code for VeraGridEngine.Devices.Injections.current_injection

# 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 __future__ import annotations

from typing import Union, Tuple
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from VeraGridEngine.enumerations import DeviceType, BuildStatus, PrpCat, ParamPowerFlowReferenceType
from VeraGridEngine.Devices.Parents.load_parent import InjectionParent
from VeraGridEngine.Devices.Parents.editable_device import get_at, GCProp
from VeraGridEngine.Devices.Profiles import ProfileFloat


[docs] class CurrentInjection(InjectionParent): """ CurrentInjection """ __slots__ = ( '_Ir', '_Ii', '_Ir_prof', '_Ii_prof', '_Ir1', '_Ii1', '_Ir1_prof', '_Ii1_prof', '_Ir2', '_Ii2', '_Ir2_prof', '_Ii2_prof', '_Ir3', '_Ii3', '_Ir3_prof', '_Ii3_prof', ) LOCAL_PROPERTY_DECLARATIONS: Tuple[GCProp, ...] = ( GCProp( prop_name='Ir', units='MW', tpe=float, definition='Active power of the current component at V=1.0 p.u.', profile_name='Ir_prof', cat=[PrpCat.PF], dyn_ref=ParamPowerFlowReferenceType.current_injection_ir_pu, ), GCProp( prop_name='Ir1', units='MW', tpe=float, definition='Active power of the current component at V=1.0 p.u.', profile_name='Ir1_prof', cat=[PrpCat.PF3], dyn_ref=ParamPowerFlowReferenceType.current_injection_ira_pu, ), GCProp( prop_name='Ir2', units='MW', tpe=float, definition='Active power of the current component at V=1.0 p.u.', profile_name='Ir2_prof', cat=[PrpCat.PF3], dyn_ref=ParamPowerFlowReferenceType.current_injection_irb_pu, ), GCProp( prop_name='Ir3', units='MW', tpe=float, definition='Active power of the current component at V=1.0 p.u.', profile_name='Ir3_prof', cat=[PrpCat.PF3], dyn_ref=ParamPowerFlowReferenceType.current_injection_irc_pu, ), GCProp( prop_name='Ii', units='MVAr', tpe=float, definition='Reactive power of the current component at V=1.0 p.u.', profile_name='Ii_prof', cat=[PrpCat.PF], dyn_ref=ParamPowerFlowReferenceType.current_injection_ii_pu, ), GCProp( prop_name='Ii1', units='MVAr', tpe=float, definition='Reactive power of the current component at V=1.0 p.u.', profile_name='Ii1_prof', cat=[PrpCat.PF3], dyn_ref=ParamPowerFlowReferenceType.current_injection_iia_pu, ), GCProp( prop_name='Ii2', units='MVAr', tpe=float, definition='Reactive power of the current component at V=1.0 p.u.', profile_name='Ii2_prof', cat=[PrpCat.PF3], dyn_ref=ParamPowerFlowReferenceType.current_injection_iib_pu, ), GCProp( prop_name='Ii3', units='MVAr', tpe=float, definition='Reactive power of the current component at V=1.0 p.u.', profile_name='Ii3_prof', cat=[PrpCat.PF3], dyn_ref=ParamPowerFlowReferenceType.current_injection_iic_pu, ), ) def __init__(self, name='CurrentInjection', idtag=None, code='', Ir=0.0, Ii=0.0, Cost=1200.0, Ir1=0.0, Ir2=0.0, Ir3=0.0, Ii1=0.0, Ii2=0.0, Ii3=0.0, active=True, mttf=0.0, mttr=0.0, capex=0, opex=0, build_status: BuildStatus = BuildStatus.Commissioned): """ The load object implements the so-called ZIP model, in which the load can be represented by a combination of power (P), current(I), and impedance (Z). The sign convention is: Positive to act as a load, negative to act as a generator. :param name: Name of the device :param idtag: UUID code :param code: secondary ID code :param Ir: Real current in equivalent MW :param Ir1: Real phase 1 current in equivalent MW :param Ir2: Real phase 2 current in equivalent MW :param Ir3: Real phase 3 current in equivalent MW :param Ii: Imaginary current in equivalent MVAr :param Ii1: Imaginary phase 1 current in equivalent MVAr :param Ii2: Imaginary phase 2 current in equivalent MVAr :param Ii3: Imaginary phase 3 current in equivalent MVAr :param Cost: Cost of load shedding :param active: Is the load active? :param mttf: Mean time to failure in hours :param mttr: Mean time to recovery in hours """ InjectionParent.__init__(self, name=name, idtag=idtag, code=code, bus=None, active=active, Cost=Cost, mttf=mttf, mttr=mttr, capex=capex, opex=opex, build_status=build_status, device_type=DeviceType.CurrentInjectionDevice) self.Ir = float(Ir) self.Ir1 = float(Ir1) self.Ir2 = float(Ir2) self.Ir3 = float(Ir3) self.Ii = float(Ii) self.Ii1 = float(Ii1) self.Ii2 = float(Ii2) self.Ii3 = float(Ii3) self._Ir_prof = ProfileFloat(default_value=self.Ir) self._Ir1_prof = ProfileFloat(default_value=self.Ir1) self._Ir2_prof = ProfileFloat(default_value=self.Ir2) self._Ir3_prof = ProfileFloat(default_value=self.Ir3) self._Ii_prof = ProfileFloat(default_value=self.Ii) self._Ii1_prof = ProfileFloat(default_value=self.Ii1) self._Ii2_prof = ProfileFloat(default_value=self.Ii2) self._Ii3_prof = ProfileFloat(default_value=self.Ii3) @property def Ir_prof(self) -> ProfileFloat: """ Cost profile :return: Profile """ return self._Ir_prof @Ir_prof.setter def Ir_prof(self, val: Union[ProfileFloat, np.ndarray]): if isinstance(val, ProfileFloat): self._Ir_prof = val elif isinstance(val, np.ndarray): self._Ir_prof.set(arr=val) else: raise Exception(str(type(val)) + 'not supported to be set into a Ir_prof')
[docs] def get_Ir_at(self, t: int | None) -> float: """ :param t: :return: """ return get_at(self.Ir, self.Ir_prof, t)
@property def Ir1_prof(self) -> ProfileFloat: """ Cost profile :return: Profile """ return self._Ir1_prof @Ir1_prof.setter def Ir1_prof(self, val: Union[ProfileFloat, np.ndarray]): if isinstance(val, ProfileFloat): self._Ir1_prof = val elif isinstance(val, np.ndarray): self._Ir1_prof.set(arr=val) else: raise Exception(str(type(val)) + 'not supported to be set into a Ir1_prof')
[docs] def get_Ir1_at(self, t: int | None) -> float: """ :param t: :return: """ return get_at(self.Ir1, self.Ir1_prof, t)
@property def Ir2_prof(self) -> ProfileFloat: """ Cost profile :return: Profile """ return self._Ir2_prof @Ir2_prof.setter def Ir2_prof(self, val: Union[ProfileFloat, np.ndarray]): if isinstance(val, ProfileFloat): self._Ir2_prof = val elif isinstance(val, np.ndarray): self._Ir2_prof.set(arr=val) else: raise Exception(str(type(val)) + 'not supported to be set into a Ir2_prof')
[docs] def get_Ir2_at(self, t: int | None) -> float: """ :param t: :return: """ return get_at(self.Ir2, self.Ir2_prof, t)
@property def Ir3_prof(self) -> ProfileFloat: """ Cost profile :return: Profile """ return self._Ir3_prof @Ir3_prof.setter def Ir3_prof(self, val: Union[ProfileFloat, np.ndarray]): if isinstance(val, ProfileFloat): self._Ir3_prof = val elif isinstance(val, np.ndarray): self._Ir3_prof.set(arr=val) else: raise Exception(str(type(val)) + 'not supported to be set into a Ir3_prof')
[docs] def get_Ir3_at(self, t: int | None) -> float: """ :param t: :return: """ return get_at(self.Ir3, self.Ir3_prof, t)
@property def Ii_prof(self) -> ProfileFloat: """ Cost profile :return: Profile """ return self._Ii_prof @Ii_prof.setter def Ii_prof(self, val: Union[ProfileFloat, np.ndarray]): if isinstance(val, ProfileFloat): self._Ii_prof = val elif isinstance(val, np.ndarray): self._Ii_prof.set(arr=val) else: raise Exception(str(type(val)) + 'not supported to be set into a Ii_prof')
[docs] def get_Ii_at(self, t: int | None) -> float: """ :param t: :return: """ return get_at(self.Ii, self.Ii_prof, t)
@property def Ii1_prof(self) -> ProfileFloat: """ Cost profile :return: Profile """ return self._Ii1_prof @Ii1_prof.setter def Ii1_prof(self, val: Union[ProfileFloat, np.ndarray]): if isinstance(val, ProfileFloat): self._Ii1_prof = val elif isinstance(val, np.ndarray): self._Ii1_prof.set(arr=val) else: raise Exception(str(type(val)) + 'not supported to be set into a Ii1_prof')
[docs] def get_Ii1_at(self, t: int | None) -> float: """ :param t: :return: """ return get_at(self.Ii1, self.Ii1_prof, t)
@property def Ii2_prof(self) -> ProfileFloat: """ Cost profile :return: Profile """ return self._Ii2_prof @Ii2_prof.setter def Ii2_prof(self, val: Union[ProfileFloat, np.ndarray]): if isinstance(val, ProfileFloat): self._Ii2_prof = val elif isinstance(val, np.ndarray): self._Ii2_prof.set(arr=val) else: raise Exception(str(type(val)) + 'not supported to be set into a Ii2_prof')
[docs] def get_Ii2_at(self, t: int | None) -> float: """ :param t: :return: """ return get_at(self.Ii2, self.Ii2_prof, t)
@property def Ii3_prof(self) -> ProfileFloat: """ Cost profile :return: Profile """ return self._Ii3_prof @Ii3_prof.setter def Ii3_prof(self, val: Union[ProfileFloat, np.ndarray]): if isinstance(val, ProfileFloat): self._Ii3_prof = val elif isinstance(val, np.ndarray): self._Ii3_prof.set(arr=val) else: raise Exception(str(type(val)) + 'not supported to be set into a Ii3_prof')
[docs] def get_Ii3_at(self, t: int | None) -> float: """ :param t: :return: """ return get_at(self.Ii3, self.Ii3_prof, t)
[docs] def get_I_at(self, t: int | None) -> complex: """ :param t: :return: """ return complex(self.get_Ir_at(t), self.get_Ii_at(t))
[docs] def get_I1_at(self, t: int | None) -> complex: """ :param t: :return: """ return complex(self.get_Ir1_at(t), self.get_Ii1_at(t))
[docs] def get_I2_at(self, t: int | None) -> complex: """ :param t: :return: """ return complex(self.get_Ir2_at(t), self.get_Ii2_at(t))
[docs] def get_I3_at(self, t: int | None) -> complex: """ :param t: :return: """ return complex(self.get_Ir3_at(t), self.get_Ii3_at(t))
[docs] def plot_profiles(self, time=None, show_fig=True): """ Plot the time series results of this object :param time: array of time values :param show_fig: Show the figure? """ if time is not None: fig = plt.figure(figsize=(12, 8)) ax_1 = fig.add_subplot(211) ax_2 = fig.add_subplot(212, sharex=ax_1) # P y = self.Ir_prof.toarray() df = pd.DataFrame(data=y, index=time, columns=[self.name]) ax_1.set_title('Active power', fontsize=14) ax_1.set_ylabel('MW', fontsize=11) df.plot(ax=ax_1) # Q y = self.Ii_prof.toarray() df = pd.DataFrame(data=y, index=time, columns=[self.name]) ax_2.set_title('Reactive power', fontsize=14) ax_2.set_ylabel('MVAr', 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 Ir(self) -> float: """ Get ``Ir``. :return: float """ return self._Ir @Ir.setter def Ir(self, val: float) -> None: """ Set ``Ir``. :param val: Value to assign. :return: None """ self._Ir = float(val) @property def Ir1(self) -> float: """ Get ``Ir1``. :return: float """ return self._Ir1 @Ir1.setter def Ir1(self, val: float) -> None: """ Set ``Ir1``. :param val: Value to assign. :return: None """ self._Ir1 = float(val) @property def Ir2(self) -> float: """ Get ``Ir2``. :return: float """ return self._Ir2 @Ir2.setter def Ir2(self, val: float) -> None: """ Set ``Ir2``. :param val: Value to assign. :return: None """ self._Ir2 = float(val) @property def Ir3(self) -> float: """ Get ``Ir3``. :return: float """ return self._Ir3 @Ir3.setter def Ir3(self, val: float) -> None: """ Set ``Ir3``. :param val: Value to assign. :return: None """ self._Ir3 = float(val) @property def Ii(self) -> float: """ Get ``Ii``. :return: float """ return self._Ii @Ii.setter def Ii(self, val: float) -> None: """ Set ``Ii``. :param val: Value to assign. :return: None """ self._Ii = float(val) @property def Ii1(self) -> float: """ Get ``Ii1``. :return: float """ return self._Ii1 @Ii1.setter def Ii1(self, val: float) -> None: """ Set ``Ii1``. :param val: Value to assign. :return: None """ self._Ii1 = float(val) @property def Ii2(self) -> float: """ Get ``Ii2``. :return: float """ return self._Ii2 @Ii2.setter def Ii2(self, val: float) -> None: """ Set ``Ii2``. :param val: Value to assign. :return: None """ self._Ii2 = float(val) @property def Ii3(self) -> float: """ Get ``Ii3``. :return: float """ return self._Ii3 @Ii3.setter def Ii3(self, val: float) -> None: """ Set ``Ii3``. :param val: Value to assign. :return: None """ self._Ii3 = float(val)