Source code for VeraGridEngine.Devices.Branches.transformer

# 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

import numpy as np
from typing import Tuple
from VeraGridEngine.basic_structures import Logger, Mat, IntVec
from VeraGridEngine.Devices.Substation.bus import Bus
from VeraGridEngine.enumerations import (WindingsConnection, BuildStatus, TapPhaseControl,
                                         TapModuleControl, TapChangerTypes, WindingType, PrpCat)
from VeraGridEngine.Devices.Parents.controllable_branch_parent import ControllableBranchParent
from VeraGridEngine.Devices.Branches.transformer_type import TransformerType, reverse_transformer_short_circuit_study
from VeraGridEngine.Devices.Parents.editable_device import DeviceType, GCProp


[docs] class Transformer2W(ControllableBranchParent): __slots__ = ( '_HV', '_LV', '_Sn', '_Pcu', '_Pfe', '_I0', '_Vsc', 'conn', 'template', 'possible_transformer_types', '_conn_f', '_conn_t', '_vector_group_number', '_phases', ) LOCAL_PROPERTY_DECLARATIONS: Tuple[GCProp, ...] = ( GCProp( prop_name='HV', units='kV', tpe=float, definition='High voltage rating', cat=[PrpCat.TP], ), GCProp( prop_name='LV', units='kV', tpe=float, definition='Low voltage rating', cat=[PrpCat.TP], ), GCProp( prop_name='Sn', units='MVA', tpe=float, definition='Nominal power', cat=[PrpCat.TP], ), GCProp( prop_name='Pcu', units='kW', tpe=float, definition='Copper losses (optional)', cat=[PrpCat.TP], ), GCProp( prop_name='Pfe', units='kW', tpe=float, definition='Iron losses (optional)', cat=[PrpCat.TP], ), GCProp( prop_name='I0', units='%', tpe=float, definition='No-load current (optional)', cat=[PrpCat.TP], ), GCProp( prop_name='Vsc', units='%', tpe=float, definition='Short-circuit voltage (optional)', cat=[PrpCat.TP], ), GCProp( prop_name='conn', units='', tpe=WindingsConnection, definition='Windings connection (from, to):G: grounded starS: ungrounded starD: delta', cat=[PrpCat.TP, PrpCat.PF3, PrpCat.SC], ), GCProp( prop_name='conn_f', units='', tpe=WindingType, definition='Winding 3 phase connection at the from side', cat=[PrpCat.TP, PrpCat.PF3, PrpCat.SC], ), GCProp( prop_name='conn_t', units='', tpe=WindingType, definition='Winding 3 phase connection at the to side', cat=[PrpCat.TP, PrpCat.PF3, PrpCat.SC], ), GCProp( prop_name='vector_group_number', units='', tpe=int, definition='Vector group number. It indicates the structural phase:' 'phase = vector_group_number Β· 30ΒΊ', cat=[PrpCat.TP, PrpCat.PF3, PrpCat.SC], ), GCProp( prop_name='template', units='', tpe=DeviceType.TransformerTypeDevice, definition='', editable=False, cat=[PrpCat.TP], ), ) def __init__(self, bus_from: Bus | None = None, bus_to: Bus | None = None, name='Branch', idtag: str | None = None, code: str = '', HV: float | None = None, LV: float | None = None, nominal_power: float = 0.001, copper_losses: float = 0.0, iron_losses: float = 0.0, no_load_current: float = 0.0, short_circuit_voltage: float = 0.0, r: float = 1e-20, x: float = 1e-5, g: float = 1e-20, b: float = 1e-20, design_rate: float = 9999.0, rate: float = 9999.0, tap_module: float = 1.0, tap_module_max: float = 1.2, tap_module_min: float = 0.5, tap_phase: float = 0.0, tap_phase_max: float = 6.28, tap_phase_min: float = -6.28, active: bool = True, reducible: bool = False, tolerance: float = 0.0, cost: float = 100.0, mttf: float = 0.0, mttr: float = 0.0, vset: float = 1.0, Pset: float = 0.0, Qset: float = 0.0, temp_base: float = 20.0, temp_oper: float = 20.0, alpha: float = 0.00330, tap_module_control_mode: TapModuleControl = TapModuleControl.fixed, tap_phase_control_mode: TapPhaseControl = TapPhaseControl.fixed, template: TransformerType | None = None, contingency_factor: float = 1.0, protection_rating_factor: float = 1.4, contingency_enabled: bool = True, monitor_loading: bool = True, r0: float = 1e-20, x0: float = 1e-20, g0: float = 1e-20, b0: float = 1e-20, r2: float = 1e-20, x2: float = 1e-20, g2: float = 1e-20, b2: float = 1e-20, conn: WindingsConnection = WindingsConnection.GG, capex: float = 0.0, opex: float = 0.0, build_status: BuildStatus = BuildStatus.Commissioned, tc_total_positions: int = 5, tc_neutral_position: int = 2, tc_normal_position: int = 2, tc_dV: float = 0.01, tc_asymmetry_angle=90, tc_type: TapChangerTypes = TapChangerTypes.NoRegulation): """ Transformer constructor :param name: Name of the branch :param idtag: UUID code :param code: secondary id :param bus_from: "From" :ref:`bus<Bus>` object :param bus_to: "To" :ref:`bus<Bus>` object :param HV: Higher voltage value in kV :param LV: Lower voltage value in kV :param nominal_power: Nominal power of the machine in MVA :param copper_losses: Copper losses in kW :param iron_losses: Iron losses in kW :param no_load_current: No load current in % :param short_circuit_voltage: Short circuit voltage in % :param r: resistance in per unit :param x: reactance in per unit :param g: shunt conductance in per unit :param b: shunt susceptance in per unit :param design_rate: Design rate (MVA) :param rate: rate in MVA :param tap_module: tap module in p.u. :param tap_module_max: :param tap_module_min: :param tap_phase: phase shift angle (rad) :param tap_phase_max: :param tap_phase_min: :param active: Is the branch active? :param tolerance: Tolerance specified for the branch impedance in % :param cost: Cost of overload (e/MW) :param mttf: Mean time to failure in hours :param mttr: Mean time to recovery in hours :param vset: Voltage set-point of the voltage controlled bus in per unit :param Pset: Power set point :param temp_base: Base temperature at which `r` is measured in Β°C :param temp_oper: Operating temperature in Β°C :param alpha: Thermal constant of the material in Β°C :param template: Branch template :param contingency_factor: Rating factor in case of contingency :param contingency_enabled: enabled for contingencies (Legacy) :param monitor_loading: monitor the loading (used in OPF) :param r0: zero-sequence resistence (p.u.) :param x0: zero-sequence reactance (p.u.) :param g0: zero-sequence conductance (p.u.) :param b0: zero-sequence susceptance (p.u.) :param r2: negative-sequence resistence (p.u.) :param x2: negative-sequence reactance (p.u.) :param g2: negative-sequence conductance (p.u.) :param b2: negative-sequence susceptance (p.u.) :param conn: transformer connection type :param capex: Cost of investment (e/MW) :param opex: Cost of operation (e/MWh) :param build_status: build status (now time) """ ControllableBranchParent.__init__(self, name=name, idtag=idtag, code=code, bus_from=bus_from, bus_to=bus_to, active=active, reducible=reducible, design_rate=design_rate, rate=rate, r=r, x=x, g=g, b=b, tap_module=tap_module, tap_module_max=tap_module_max, tap_module_min=tap_module_min, tap_phase=tap_phase, tap_phase_max=tap_phase_max, tap_phase_min=tap_phase_min, tolerance=tolerance, cost=cost, mttf=mttf, mttr=mttr, vset=vset, Pset=Pset, Qset=Qset, regulation_branch=None, regulation_bus=None, temp_base=temp_base, temp_oper=temp_oper, alpha=alpha, # control_mode=control_mode, tap_module_control_mode=tap_module_control_mode, tap_phase_control_mode=tap_phase_control_mode, contingency_factor=contingency_factor, protection_rating_factor=protection_rating_factor, contingency_enabled=contingency_enabled, monitor_loading=monitor_loading, r0=r0, x0=x0, g0=g0, b0=b0, r2=r2, x2=x2, g2=g2, b2=b2, capex=capex, opex=opex, build_status=build_status, device_type=DeviceType.Transformer2WDevice, tc_total_positions=tc_total_positions, tc_neutral_position=tc_neutral_position, tc_normal_position=tc_normal_position, tc_dV=tc_dV, tc_asymmetry_angle=tc_asymmetry_angle, tc_type=tc_type) # set the high and low voltage values self._HV: float | None = None if HV is None else float(HV) self._LV: float | None = None if LV is None else float(LV) if self.bus_from and self.bus_to: self.set_hv_and_lv(HV, LV) self.Sn = float(nominal_power) self.Pcu = float(copper_losses) self.Pfe = float(iron_losses) self.I0 = float(no_load_current) self.Vsc = float(short_circuit_voltage) # connection type self.conn: WindingsConnection = conn # type template self.template: TransformerType | None = template # association with transformer templates # self.possible_transformer_types: Associations = Associations(device_type=DeviceType.TransformerTypeDevice) self._conn_f: WindingType = WindingType.GroundedStar self._conn_t: WindingType = WindingType.GroundedStar self._vector_group_number: int = 0 self._phases: IntVec = np.array([1, 2, 3]) # TODO: do we need to edit the phases vector? @property def conn_f(self) -> WindingType: return self._conn_f @conn_f.setter def conn_f(self, val: WindingType): if isinstance(val, WindingType): self._conn_f = val else: raise Exception("Conn_f is not a WindingType") @property def conn_t(self) -> WindingType: return self._conn_t @conn_t.setter def conn_t(self, val: WindingType): if isinstance(val, WindingType): self._conn_t = val else: raise Exception("Conn_t is not a WindingType") @property def vector_group_number(self) -> int: return self._vector_group_number @vector_group_number.setter def vector_group_number(self, val: int): val = int(val) if 0 <= val <= 11: self._vector_group_number = val else: print("Vector group out of range (0-11)") @property def phases(self) -> IntVec: return self._phases @phases.setter def phases(self, val: IntVec): if isinstance(val, np.ndarray): self._phases = val else: raise Exception("phases must be a numpy array (IntVec)")
[docs] def set_hv_and_lv(self, HV: float | None, LV: float | None): """ set the high and low voltage values :param HV: higher voltage value (kV) :param LV: lower voltage value (kV) """ if self.bus_from is not None: vh = max(self.bus_from.Vnom, self.bus_to.Vnom) vl = min(self.bus_from.Vnom, self.bus_to.Vnom) else: vh = 1.0 vl = 1.0 if HV is None: self.HV = vh else: self.HV = HV if LV is None: self.LV = vl else: self.LV = LV
[docs] def get_from_to_nominal_voltages(self) -> Tuple[float, float, bool]: """ :return: """ bus_f_v = self.bus_from.Vnom bus_t_v = self.bus_to.Vnom dhf = abs(self.HV - bus_f_v) dht = abs(self.HV - bus_t_v) if dhf < dht: # the HV side is on the from side tpe_f_v = self.HV tpe_t_v = self.LV hv_at_from = True else: # the HV side is on the to side tpe_t_v = self.HV tpe_f_v = self.LV hv_at_from = False return tpe_f_v, tpe_t_v, hv_at_from
[docs] def get_virtual_taps(self) -> Tuple[float, float]: """ Get the branch virtual taps The virtual taps generate when a transformer nominal winding voltage differs from the bus nominal voltage. :return: Virtual tap at the *from* side, **tap_t** (float, 1.0): Virtual tap at the *to* side """ # resolve how the transformer is actually connected and set the virtual taps bus_f_v = self.bus_from.Vnom bus_t_v = self.bus_to.Vnom # obtain the nominal voltages at the from and to sides tpe_f_v, tpe_t_v, _ = self.get_from_to_nominal_voltages() tap_f = tpe_f_v / bus_f_v if bus_f_v > 0 else 1.0 tap_t = tpe_t_v / bus_t_v if bus_t_v > 0 else 1.0 if tap_f == 0.0: tap_f = 1.0 if tap_t == 0.0: tap_t = 1.0 return tap_f, tap_t
[docs] def apply_template(self, obj: TransformerType, Sbase: float, logger=Logger()): """ Apply a branch template to this object :param obj: TransformerType or Tower object :param Sbase: circuit base power in MVA :param logger: Log list """ if isinstance(obj, TransformerType): self.HV = obj.HV self.LV = obj.LV # get the transformer impedance in the base of the transformer z_series, y_shunt = obj.get_impedances(VH=obj.HV, VL=obj.LV, Sbase=Sbase) self.R = z_series.real self.X = z_series.imag self.G = y_shunt.real self.B = y_shunt.imag self.rate = obj.Sn self.rate_prof.fill(self.rate) self.Sn = obj.Sn self.Pcu = obj.Pcu self.Pfe = obj.Pfe self.I0 = obj.I0 self.Vsc = obj.Vsc self.tap_changer = obj.get_tap_changer() # set the from and to connection types of the windings _, _, hv_at_from = self.get_from_to_nominal_voltages() if hv_at_from: self.conn_f = obj.conn_hv self.conn_t = obj.conn_lv else: self.conn_t = obj.conn_hv self.conn_f = obj.conn_lv if self.template is not None: if obj != self.template: self.template = obj else: logger.add_error('Template not recognised', self.name) else: self.template = obj self.rms_template = obj.rms_template self.emt_template = obj.emt_template
[docs] def delete_virtual_taps(self): """ Set the HV and LV parameters such that any virtual tap is null """ self.HV = max(self.bus_from.Vnom, self.bus_to.Vnom) self.LV = min(self.bus_from.Vnom, self.bus_to.Vnom)
[docs] def fix_inconsistencies(self, logger: Logger, maximum_difference=0.1) -> bool: """ Fix the inconsistencies :param logger: :param maximum_difference: proportion to be under or above (i.e. Transformer HV=41.9, bus HV=45 41.9/45 = 0.93 -> 0.9 <= 0.93 <= 1.1, so it's ok :return: were there any errors? """ errors = False HV = max(self.bus_from.Vnom, self.bus_to.Vnom) LV = min(self.bus_from.Vnom, self.bus_to.Vnom) if self.LV > self.HV: logger.add_warning("HV > LV", self.name, self.HV, HV) self.HV, self.LV = self.LV, self.HV errors = True rHV = self.HV / HV rLV = self.LV / LV LB = 1 - maximum_difference UB = 1 + maximum_difference if not (LB <= rHV <= UB): logger.add_warning("Corrected transformer HV", self.name, self.HV, HV) self.HV = HV errors = True if not (LB <= rLV <= UB): logger.add_warning("Corrected transformer LV", self.name, self.LV, LV) self.LV = LV errors = True if self.R < 0.0: logger.add_warning("Corrected transformer R<0", self.name, self.R, -self.R) self.R = -self.R errors = True return errors
[docs] def fill_design_properties(self, Pcu: float, Pfe: float, I0: float, Vsc: float, Sbase: float, round_vals: bool = False) -> "Transformer2W": """ Fill R, X, G, B from the short circuit study values :param Pcu: copper_losses (kW) :param Pfe: Iron losses (kW) :param I0: No load current in % :param Vsc: Short circuit voltage (%) :param Sbase: Base power in MVA (take always 100 MVA) :param round_vals: round the values? :return: self pointer """ if self.Sn > 0: nominal_power = self.Sn else: if self.rate > 0: nominal_power = self.rate print(f"{self.name}: Using rate to set compute the impedances...please fill a valid nominal power") else: nominal_power = 1.0 print(f"{self.name}: Using 1 to set compute the impedances...please fill a valid nominal power") tpe = TransformerType(hv_nominal_voltage=self.HV, lv_nominal_voltage=self.LV, nominal_power=nominal_power, copper_losses=Pcu, iron_losses=Pfe, no_load_current=I0, short_circuit_voltage=Vsc, gr_hv1=0.5, gx_hv1=0.5, name='type from ' + self.name) self.Pcu = Pcu self.Pfe = Pfe self.I0 = I0 self.Vsc = Vsc z_series, y_shunt = tpe.get_impedances(VH=self.HV, VL=self.LV, Sbase=Sbase) if round_vals: self.R = np.round(z_series.real, 6) self.X = np.round(z_series.imag, 6) self.G = np.round(y_shunt.real, 6) self.B = np.round(y_shunt.imag, 6) else: self.R = z_series.real self.X = z_series.imag self.G = y_shunt.real self.B = y_shunt.imag return self
[docs] def get_vcc(self) -> float: """ Get the short circuit voltage in % This is the value from the short circuit study :return: value in % """ return 100.0 * np.sqrt(self.R * self.R + self.X * self.X)
[docs] def get_transformer_type(self, Sbase: float = 100.0) -> TransformerType: """ Get the equivalent transformer type of this transformer :return: SequenceLineType :param Sbase: :return: """ if self.Vsc == 0: Pfe, Pcu, Vsc, I0, Sn = reverse_transformer_short_circuit_study(R=self.R, X=self.X, G=self.G, B=self.B, rate=self.rate, Sbase=Sbase) else: Pfe = self.Pfe Pcu = self.Pcu Vsc = self.Vsc I0 = self.I0 Sn = self.Sn tpe = TransformerType(hv_nominal_voltage=self.HV, lv_nominal_voltage=self.LV, nominal_power=Sn, copper_losses=Pcu, iron_losses=Pfe, no_load_current=I0, short_circuit_voltage=Vsc, gr_hv1=0.5, gx_hv1=0.5, name='type from ' + self.name) return tpe
[docs] def transformer_phases(self, logger: Logger): phaseN = phaseA = phaseB = phaseC = 0 for phase in self.phases: if phase == 0: phaseN = 1 elif phase == 1: phaseA = 1 elif phase == 2: phaseB = 1 elif phase == 3: phaseC = 1 else: logger.add_error( f"transformer_phases: Incorrect phase value {phase} in {self.name}", device=self.name ) return phaseN, phaseA, phaseB, phaseC return phaseN, phaseA, phaseB, phaseC
[docs] def transformer_admittance(self, vtap_f: float, vtap_t: float, logger: Logger) -> Tuple[Mat, Mat, Mat, Mat]: """ Get the transformer 3-phase primitives :param vtap_f: virtual tap from :param vtap_t: virtual tap to :param logger: Logger :return: 3x3 matrices -> Yff, Yft, Ytf, Ytt """ conn_y_from = self.conn_f == WindingType.NeutralStar or self.conn_f == WindingType.GroundedStar conn_y_to = self.conn_t == WindingType.NeutralStar or self.conn_t == WindingType.GroundedStar # phase_displacement = np.deg2rad(self.vector_group_number * 30.0) if self.conn_f == WindingType.Delta and conn_y_to: # Dy phase_displacement = np.deg2rad(60.0) elif conn_y_from and self.conn_t == WindingType.Delta: # Yd phase_displacement = np.deg2rad(0.0) else: phase_displacement = 0.0 ys = 1.0 / (self.R + 1j * self.X + 1e-20) ysh = self.G + 1j * self.B yff = (ys + ysh / 2) / (self.tap_module * self.tap_module * vtap_f * vtap_f) yft = -ys / (self.tap_module * np.exp(-1.0j * (self.tap_phase + phase_displacement)) * vtap_f * vtap_t) ytf = -ys / (self.tap_module * np.exp(1.0j * (self.tap_phase + phase_displacement)) * vtap_t * vtap_f) ytt = (ys + ysh / 2) / (vtap_t * vtap_t) if conn_y_from and conn_y_to: # Yy Yff = np.array([ [0, 0, 0, 0], [0, yff, 0, 0], [0, 0, yff, 0], [0, 0, 0, yff] ]) Yft = np.array([ [0, 0, 0, 0], [0, yft, 0, 0], [0, 0, yft, 0], [0, 0, 0, yft] ]) Ytf = np.array([ [0, 0, 0, 0], [0, ytf, 0, 0], [0, 0, ytf, 0], [0, 0, 0, ytf] ]) Ytt = np.array([ [0, 0, 0, 0], [0, ytt, 0, 0], [0, 0, ytt, 0], [0, 0, 0, ytt] ]) elif conn_y_from and self.conn_t == WindingType.Delta: # 'Yd' Yff = np.array([ [0, 0, 0, 0], [0, yff, 0, 0], [0, 0, yff, 0], [0, 0, 0, yff] ]) Yft = np.array([ [0, 0, 0, 0], [0, yft / np.sqrt(3), -yft / np.sqrt(3), 0], [0, 0, yft / np.sqrt(3), -yft / np.sqrt(3)], [0, -yft / np.sqrt(3), 0, yft / np.sqrt(3)] ]) Ytf = np.array([ [0, 0, 0, 0], [0, ytf / np.sqrt(3), 0, -ytf / np.sqrt(3)], [0, -ytf / np.sqrt(3), ytf / np.sqrt(3), 0], [0, 0, -ytf / np.sqrt(3), ytf / np.sqrt(3)] ]) Ytt = np.array([ [0, 0, 0, 0], [0, 2 * ytt / 3, -ytt / 3, -ytt / 3], [0, -ytt / 3, 2 * ytt / 3, -ytt / 3], [0, -ytt / 3, -ytt / 3, 2 * ytt / 3] ]) elif conn_y_from and self.conn_t == WindingType.ZigZag: # 'Yz' Yff = np.array([ [yff, 0, 0], [0, yff, 0], [0, 0, yff] ]) Yft = np.array([ [yft / 2, 0, -yft / 2], [-yft / 2, yft / 2, 0], [0, -yft / 2, yft / 2] ]) Ytf = np.array([ [ytf / 2, -ytf / 2, 0], [0, ytf / 2, -ytf / 2], [-ytf / 2, 0, ytf / 2] ]) Ytt = np.array([ [ytt, 0, 0], [0, ytt, 0], [0, 0, ytt] ]) elif self.conn_f == WindingType.Delta and conn_y_to: # 'Dy' Yff = np.array([ [0, 0, 0, 0], [0, 2 * yff / 3, -yff / 3, -yff / 3], [0, -yff / 3, 2 * yff / 3, -yff / 3], [0, -yff / 3, -yff / 3, 2 * yff / 3] ]) Yft = np.array([ [0, 0, 0, 0], [0, yft / np.sqrt(3), 0, -yft / np.sqrt(3)], [0, -yft / np.sqrt(3), yft / np.sqrt(3), 0], [0, 0, -yft / np.sqrt(3), yft / np.sqrt(3)] ]) Ytf = np.array([ [0, 0, 0, 0], [0, ytf / np.sqrt(3), -ytf / np.sqrt(3), 0], [0, 0, ytf / np.sqrt(3), -ytf / np.sqrt(3)], [0, -ytf / np.sqrt(3), 0, ytf / np.sqrt(3)] ]) Ytt = np.array([ [0, 0, 0, 0], [0, ytt, 0, 0], [0, 0, ytt, 0], [0, 0, 0, ytt] ]) elif self.conn_f == WindingType.Delta and self.conn_t == WindingType.Delta: # 'Dd' Yff = np.array([ [0, 0, 0, 0], [0, 2 * yff / 3, -yff / 3, -yff / 3], [0, -yff / 3, 2 * yff / 3, -yff / 3], [0, -yff / 3, -yff / 3, 2 * yff / 3] ]) Yft = np.array([ [0, 0, 0, 0], [0, 2 * yft / 3, -yft / 3, -yft / 3], [0, -yft / 3, 2 * yft / 3, -yft / 3], [0, -yft / 3, -yft / 3, 2 * yft / 3] ]) Ytf = np.array([ [0, 0, 0, 0], [0, 2 * ytf / 3, -ytf / 3, -ytf / 3], [0, -ytf / 3, 2 * ytf / 3, -ytf / 3], [0, -ytf / 3, -ytf / 3, 2 * ytf / 3] ]) Ytt = np.array([ [0, 0, 0, 0], [0, 2 * ytt / 3, -ytt / 3, -ytt / 3], [0, -ytt / 3, 2 * ytt / 3, -ytt / 3], [0, -ytt / 3, -ytt / 3, 2 * ytt / 3] ]) elif self.conn_f == WindingType.Delta and self.conn_t == WindingType.ZigZag: # 'Dz': Yff = np.array([ [2 * yff / 3, -yff / 3, -yff / 3], [-yff / 3, 2 * yff / 3, -yff / 3], [-yff / 3, -yff / 3, 2 * yff / 3] ]) Yft = np.array([ [yft / (2 * np.sqrt(3)), yft / (2 * np.sqrt(3)), -yft / np.sqrt(3)], [-yft / np.sqrt(3), yft / (2 * np.sqrt(3)), yft / (2 * np.sqrt(3))], [yft / (2 * np.sqrt(3)), -yft / np.sqrt(3), yft / (2 * np.sqrt(3))] ]) Ytf = np.array([ [yft / (2 * np.sqrt(3)), -yft / np.sqrt(3), yft / (2 * np.sqrt(3))], [yft / (2 * np.sqrt(3)), yft / (2 * np.sqrt(3)), -yft / np.sqrt(3)], [-yft / np.sqrt(3), yft / (2 * np.sqrt(3)), yft / (2 * np.sqrt(3))] ]) Ytt = np.array([ [ytt, 0, 0], [0, ytt, 0], [0, 0, ytt] ]) elif self.conn_f == WindingType.ZigZag and conn_y_to: # 'Zy': Yff = np.array([ [yff, 0, 0], [0, yff, 0], [0, 0, yff] ]) Yft = np.array([ [yft / 2, -yft / 2, 0], [0, yft / 2, -yft / 2], [-yft / 2, 0, yft / 2] ]) Ytf = np.array([ [ytf / 2, 0, -ytf / 2], [-ytf / 2, ytf / 2, 0], [0, -ytf / 2, ytf / 2] ]) Ytt = np.array([ [ytt, 0, 0], [0, ytt, 0], [0, 0, ytt] ]) elif self.conn_f == WindingType.ZigZag and self.conn_t == WindingType.Delta: # 'Zd': Yff = np.array([ [yff, 0, 0], [0, yff, 0], [0, 0, yff] ]) Yft = np.array([ [yft / (2 * np.sqrt(3)), -yft / np.sqrt(3), yft / (2 * np.sqrt(3))], [yft / (2 * np.sqrt(3)), yft / (2 * np.sqrt(3)), -yft / np.sqrt(3)], [-yft / np.sqrt(3), yft / (2 * np.sqrt(3)), yft / (2 * np.sqrt(3))] ]) Ytf = np.array([ [yft / (2 * np.sqrt(3)), yft / (2 * np.sqrt(3)), -yft / np.sqrt(3)], [-yft / np.sqrt(3), yft / (2 * np.sqrt(3)), yft / (2 * np.sqrt(3))], [yft / (2 * np.sqrt(3)), -yft / np.sqrt(3), yft / (2 * np.sqrt(3))] ]) Ytt = np.array([ [2 * ytt / 3, -ytt / 3, -ytt / 3], [-ytt / 3, 2 * ytt / 3, -ytt / 3], [-ytt / 3, -ytt / 3, 2 * ytt / 3] ]) elif self.conn_f == WindingType.ZigZag and self.conn_t == WindingType.ZigZag: # 'Zz': Yff = np.array([ [yff, 0, 0], [0, yff, 0], [0, 0, yff] ]) Yft = np.array([ [yft, 0, 0], [0, yft, 0], [0, 0, yft] ]) Ytf = np.array([ [ytf, 0, 0], [0, ytf, 0], [0, 0, ytf] ]) Ytt = np.array([ [ytt, 0, 0], [0, ytt, 0], [0, 0, ytt] ]) else: logger.add_error("transformer_admittance: Unknown vector group", device=self.name) zeros = np.zeros((4, 4), dtype=float) return zeros, zeros, zeros, zeros return Yff, Yft, Ytf, Ytt
# Scalar property accessors coerce assignments to the declared schema types. @property def HV(self) -> float: """ Get ``HV``. :return: float """ return self._HV @HV.setter def HV(self, val: float) -> None: """ Set ``HV``. :param val: Value to assign. :return: None """ self._HV = float(val) @property def LV(self) -> float: """ Get ``LV``. :return: float """ return self._LV @LV.setter def LV(self, val: float) -> None: """ Set ``LV``. :param val: Value to assign. :return: None """ self._LV = float(val) @property def Sn(self) -> float: """ Get ``Sn``. :return: float """ return self._Sn @Sn.setter def Sn(self, val: float) -> None: """ Set ``Sn``. :param val: Value to assign. :return: None """ self._Sn = float(val) @property def Pcu(self) -> float: """ Get ``Pcu``. :return: float """ return self._Pcu @Pcu.setter def Pcu(self, val: float) -> None: """ Set ``Pcu``. :param val: Value to assign. :return: None """ self._Pcu = float(val) @property def Pfe(self) -> float: """ Get ``Pfe``. :return: float """ return self._Pfe @Pfe.setter def Pfe(self, val: float) -> None: """ Set ``Pfe``. :param val: Value to assign. :return: None """ self._Pfe = float(val) @property def I0(self) -> float: """ Get ``I0``. :return: float """ return self._I0 @I0.setter def I0(self, val: float) -> None: """ Set ``I0``. :param val: Value to assign. :return: None """ self._I0 = float(val) @property def Vsc(self) -> float: """ Get ``Vsc``. :return: float """ return self._Vsc @Vsc.setter def Vsc(self, val: float) -> None: """ Set ``Vsc``. :param val: Value to assign. :return: None """ self._Vsc = float(val)