Source code for VeraGridEngine.Devices.measurement

# 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
from VeraGridEngine.Devices.Parents.editable_device import get_at, GCProp
from VeraGridEngine.Devices.Parents.pointer_device_parent import PointerDeviceParent
from VeraGridEngine.Devices.Substation.bus import Bus
from VeraGridEngine.Devices.Branches.line import Line
from VeraGridEngine.Devices.Branches.dc_line import DcLine
from VeraGridEngine.Devices.Branches.transformer import Transformer2W
from VeraGridEngine.Devices.Branches.winding import Winding
from VeraGridEngine.Devices.Branches.switch import Switch
from VeraGridEngine.Devices.Branches.series_reactance import SeriesReactance
from VeraGridEngine.Devices.Branches.upfc import UPFC
from VeraGridEngine.Devices.Injections.generator import Generator
from VeraGridEngine.Devices.Profiles import ProfileFloat
from VeraGridEngine.enumerations import DeviceType
from VeraGridEngine.basic_structures import Vec

# NOTE: These areas here because this object loads first than the types file with the types aggregations

SE_BRANCH_TYPES = Union[
    Line,
    DcLine,
    Transformer2W,
    UPFC,
    Winding,
    Switch,
    SeriesReactance,
    Generator
]
MEASURABLE_OBJECT = Union[Bus, SE_BRANCH_TYPES]


[docs] class MeasurementTemplate(PointerDeviceParent): """ Measurement class """ __slots__ = ( '_value', '_value_prof', '_sigma', '_sigma_prof', ) LOCAL_PROPERTY_DECLARATIONS: Tuple[GCProp, ...] = ( GCProp( prop_name="value", tpe=float, profile_name="value_prof", definition="Value of the measurement", ), GCProp( prop_name="sigma", tpe=float, profile_name="sigma_prof", definition="Uncertainty of the measurement", ), ) def __init__(self, value: float, uncertainty: float, api_obj: MEASURABLE_OBJECT, name: str, idtag: Union[str, None], device_type: DeviceType): """ Constructor :param value: value :param uncertainty: uncertainty (standard deviation) :param api_obj: :param name: :param idtag: """ PointerDeviceParent.__init__(self, idtag=idtag, device=api_obj, code="", name=name, device_type=device_type, comment="") self.value = float(value) self.sigma = float(uncertainty) self._value_prof = ProfileFloat(default_value=self.value) self._sigma_prof = ProfileFloat(default_value=self.sigma) @property def value_prof(self) -> ProfileFloat: """ Cost profile :return: Profile """ return self._value_prof @value_prof.setter def value_prof(self, val: Union[ProfileFloat, Vec]): if isinstance(val, ProfileFloat): self._value_prof = val elif isinstance(val, np.ndarray): self._value_prof.set(arr=val) else: raise Exception(str(type(val)) + 'not supported to be set into a value_prof')
[docs] def get_value_at(self, t: int | None) -> float: """ :param t: :return: """ return get_at(self.value, self.value_prof, t)
@property def sigma_prof(self) -> ProfileFloat: """ Cost profile :return: Profile """ return self._sigma_prof @sigma_prof.setter def sigma_prof(self, val: Union[ProfileFloat, np.ndarray]): if isinstance(val, ProfileFloat): self._sigma_prof = val elif isinstance(val, np.ndarray): self._sigma_prof.set(arr=val) else: raise Exception(str(type(val)) + 'not supported to be set into a sigma_prof')
[docs] def get_sigma_at(self, t: int | None) -> float: """ :param t: :return: """ return get_at(self.sigma, self.sigma_prof, t)
[docs] def get_value_pu_at(self, t: int | None, Sbase: float): """ Get measurement per-unit value at a given point :param t: None for snapshot, integer for time point :param Sbase: Base power (100 MVA) :return: value in p.u. """ return self.get_value_at(t) / Sbase
[docs] def get_standard_deviation_pu_at(self, t: int | None, Sbase: float): """ Get measurement per-unit standard deviation at a given point :param t: None for snapshot, integer for time point :param Sbase: Base power (100 MVA) :return: value in p.u. """ return self.get_sigma_at(t) / Sbase
# Scalar property accessors coerce assignments to the declared schema types. @property def value(self) -> float: """ Get ``value``. :return: float """ return self._value @value.setter def value(self, val: float) -> None: """ Set ``value``. :param val: Value to assign. :return: None """ self._value = float(val) @property def sigma(self) -> float: """ Get ``sigma``. :return: float """ return self._sigma @sigma.setter def sigma(self, val: float) -> None: """ Set ``sigma``. :param val: Value to assign. :return: None """ self._sigma = float(val)
[docs] class PiMeasurement(MeasurementTemplate): """ Measurement class """ def __init__(self, value: float = 0.0, uncertainty: float = 0.0, api_obj: Bus | None = None, name="", idtag: Union[str, None] = None): """ Bus active power injection measurement :param value: value in MW :param uncertainty: standard deviation in MW :param api_obj: bus object :param name: name :param idtag: idtag """ MeasurementTemplate.__init__(self, value=value, uncertainty=uncertainty, api_obj=api_obj, name=name, idtag=idtag, device_type=DeviceType.PiMeasurementDevice)
[docs] class QiMeasurement(MeasurementTemplate): """ Measurement class """ def __init__(self, value: float = 0.0, uncertainty: float = 0.0, api_obj: Bus | None = None, name="", idtag: Union[str, None] = None): """ Bus reactive power injection measurement :param value: value in MVAr :param uncertainty: standard deviation in MVAr :param api_obj: bus object :param name: name :param idtag: idtag """ MeasurementTemplate.__init__(self, value=value, uncertainty=uncertainty, api_obj=api_obj, name=name, idtag=idtag, device_type=DeviceType.QiMeasurementDevice)
[docs] class PgMeasurement(MeasurementTemplate): """ Measurement class """ def __init__(self, value: float = 0.0, uncertainty: float = 0.0, api_obj: Generator | None = None, name="", idtag: Union[str, None] = None): """ Generator active power injection measurement :param value: value in MW :param uncertainty: standard deviation in MW :param api_obj: bus object :param name: name :param idtag: idtag """ MeasurementTemplate.__init__(self, value=value, uncertainty=uncertainty, api_obj=api_obj, name=name, idtag=idtag, device_type=DeviceType.PgMeasurementDevice)
[docs] class QgMeasurement(MeasurementTemplate): """ Measurement class """ def __init__(self, value: float = 0.0, uncertainty: float = 0.0, api_obj: Generator | None = None, name="", idtag: Union[str, None] = None): """ Generator reactive power injection measurement :param value: value in MVAr :param uncertainty: standard deviation in MVAr :param api_obj: bus object :param name: name :param idtag: idtag """ MeasurementTemplate.__init__(self, value=value, uncertainty=uncertainty, api_obj=api_obj, name=name, idtag=idtag, device_type=DeviceType.QgMeasurementDevice)
[docs] class VmMeasurement(MeasurementTemplate): """ Measurement class """ def __init__(self, value: float = 0.0, uncertainty: float = 0.0, api_obj: Bus | None = None, name="", idtag: Union[str, None] = None): MeasurementTemplate.__init__(self, value=value, uncertainty=uncertainty, api_obj=api_obj, name=name, idtag=idtag, device_type=DeviceType.VmMeasurementDevice)
[docs] class VaMeasurement(MeasurementTemplate): """ Measurement class """ def __init__(self, value: float = 0.0, uncertainty: float = 0.0, api_obj: Bus | None = None, name="", idtag: Union[str, None] = None): MeasurementTemplate.__init__(self, value=value, uncertainty=uncertainty, api_obj=api_obj, name=name, idtag=idtag, device_type=DeviceType.VaMeasurementDevice)
[docs] class PfMeasurement(MeasurementTemplate): """ Measurement class """ def __init__(self, value: float = 0.0, uncertainty: float = 0.0, api_obj: SE_BRANCH_TYPES | None = None, name="", idtag: Union[str, None] = None): """ PfMeasurement :param value: Power flow in MW :param uncertainty: standard deviation in MW :param api_obj: a branch :param name: name :param idtag: idtag """ MeasurementTemplate.__init__(self, value=value, uncertainty=uncertainty, api_obj=api_obj, name=name, idtag=idtag, device_type=DeviceType.PfMeasurementDevice)
[docs] class QfMeasurement(MeasurementTemplate): """ Measurement class """ def __init__(self, value: float = 0.0, uncertainty: float = 0.0, api_obj: SE_BRANCH_TYPES | None = None, name="", idtag: Union[str, None] = None): """ QfMeasurement :param value: Power flow in MVAr :param uncertainty: standard deviation in MVAr :param api_obj: a branch :param name: name :param idtag: idtag """ MeasurementTemplate.__init__(self, value=value, uncertainty=uncertainty, api_obj=api_obj, name=name, idtag=idtag, device_type=DeviceType.QfMeasurementDevice)
[docs] class PtMeasurement(MeasurementTemplate): """ Measurement class """ def __init__(self, value: float = 0.0, uncertainty: float = 0.0, api_obj: SE_BRANCH_TYPES | None = None, name="", idtag: Union[str, None] = None): """ PtMeasurement :param value: Power flow in MW :param uncertainty: standard deviation in MW :param api_obj: a branch :param name: name :param idtag: idtag """ MeasurementTemplate.__init__(self, value=value, uncertainty=uncertainty, api_obj=api_obj, name=name, idtag=idtag, device_type=DeviceType.PtMeasurementDevice)
[docs] class QtMeasurement(MeasurementTemplate): """ Measurement class """ def __init__(self, value: float = 0.0, uncertainty: float = 0.0, api_obj: SE_BRANCH_TYPES | None = None, name="", idtag: Union[str, None] = None): """ QtMeasurement :param value: Power flow in MVAr :param uncertainty: standard deviation in MVAr :param api_obj: a branch :param name: name :param idtag: idtag """ MeasurementTemplate.__init__(self, value=value, uncertainty=uncertainty, api_obj=api_obj, name=name, idtag=idtag, device_type=DeviceType.QtMeasurementDevice)
[docs] def get_i_base(Sbase, Vbase): return Sbase / (Vbase * 1.732050808)
[docs] class IfMeasurement(MeasurementTemplate): """ Measurement class """ def __init__(self, value: float = 0.0, uncertainty: float = 0.0, api_obj: SE_BRANCH_TYPES | None = None, name="", idtag: Union[str, None] = None): """ IfMeasurement :param value: current flow in kA, note this is the absolute value :param uncertainty: standard deviation in kA :param api_obj: a branch :param name: name :param idtag: idtag """ MeasurementTemplate.__init__(self, value=value, uncertainty=uncertainty, api_obj=api_obj, name=name, idtag=idtag, device_type=DeviceType.IfMeasurementDevice)
[docs] def get_value_pu_at(self, t: int | None, Sbase: float): return self.get_value_at(t) / get_i_base(Sbase, Vbase=self.api_object.bus_from.Vnom)
[docs] def get_standard_deviation_pu_at(self, t: int | None, Sbase: float): return self.get_sigma_at(t) / get_i_base(Sbase, Vbase=self.api_object.bus_from.Vnom)
[docs] class ItMeasurement(MeasurementTemplate): """ Measurement class """ def __init__(self, value: float = 0.0, uncertainty: float = 0.0, api_obj: SE_BRANCH_TYPES | None = None, name="", idtag: Union[str, None] = None): """ ItMeasurement :param value: current flow in kA, note this is the absolute value :param uncertainty: standard deviation in kA :param api_obj: a branch :param name: name :param idtag: idtag """ MeasurementTemplate.__init__(self, value=value, uncertainty=uncertainty, api_obj=api_obj, name=name, idtag=idtag, device_type=DeviceType.ItMeasurementDevice) @property def device(self) -> SE_BRANCH_TYPES: """ device getter :return: """ return self._device
[docs] def get_value_pu_at(self, t: int | None, Sbase: float): return self.value / get_i_base(Sbase, Vbase=self.device.bus_to.Vnom)
[docs] def get_standard_deviation_pu_at(self, t: int | None, Sbase: float): return self.sigma / get_i_base(Sbase, Vbase=self.device.bus_to.Vnom)