hermess.devices.pss =================== .. py:module:: hermess.devices.pss Attributes ---------- .. autoapisummary:: hermess.devices.pss.PSS_REGISTRY Classes ------- .. autoapisummary:: hermess.devices.pss.PSS hermess.devices.pss.PSSKundur hermess.devices.pss.PSSSEA Module Contents --------------- .. py:class:: PSS Bases: :py:obj:`abc.ABC` Abstract base class for Power System Stabilizer models (pluggable strategy). A PSS adds a supplementary stabilizing signal 'Vs' to the AVR's voltage summing junction (the regulator error becomes ``Vf_ref - Vt + Vs``). Unlike the AVR and governor, whose outputs couple directly into the machine, the PSS couples into *another strategy* (the AVR). This is kept **host-mediated**: the PSS declares 'Vs' as its coupling variable, the host exposes it via ``Synchronous.pss_signal`` (which returns 0 when no PSS is present), and each AVR reads ``host.pss_signal(dae)`` at its summing junction. The PSS never references the AVR directly -- the host is the wiring hub. 'Vs' may be a differential state or, more typically, a device-private algebraic (a washout + lead-lag chain has direct feedthrough on the input, so its output is algebraic). Symmetric to :class:`~hermess.devices.avr.AVR` and :class:`~hermess.devices.governor.Governor`: the PSS declares what states / private algebraics / parameters it needs and the host registers them on itself. It reads the machine's **absolute** per-unit speed via ``host.omega`` (1.0 at synchronism) and forms the deviation from nominal (``dae.omega_net`` = 1 p.u.) itself. There is NO default PSS: a machine without one supplies no signal to its AVR. .. py:method:: states() -> List[str] :abstractmethod: Return ordered list of differential-state names. .. py:method:: algebs() -> List[str] Return ordered list of device-private *algebraic* variable names. A washout + lead-lag PSS returns ['Vs'] here (its output has direct feedthrough on the speed deviation, hence is algebraic) and writes the defining residual ``0 = -Vs + `` into ``dae.g`` in :meth:`fgcall`. .. py:method:: algebs_units() -> Dict[str, str] Units for each private algebraic (mirrors :meth:`units`). .. py:method:: algebs_x0() -> Dict[str, float] Initial guess for each private algebraic (Newton guess in finit). .. py:method:: units() -> List[str] :abstractmethod: Return units for each state, same length as states(). .. py:method:: params() -> Dict[str, float] :abstractmethod: Return dict of parameter names -> default values. .. py:method:: x0() -> Dict[str, float] :abstractmethod: Return default initial guess for each state. .. py:method:: descriptions() -> Dict[str, str] :abstractmethod: Return descriptions for states and params. .. py:method:: setpoints() -> Dict[str, float] Return setpoint names -> defaults. A speed-input PSS has none. .. py:method:: fgcall(host, dae: hermess.system.Dae) -> None :abstractmethod: Write the PSS's differential equations into ``dae.f`` and, if it declares private algebraics (e.g. an algebraic 'Vs'), their defining residuals into ``dae.g``. :param host: The Synchronous machine instance. Access state/algebraic indices via host.vw, host.Vs, etc., parameters via host.K_stab, host.Tw, ..., and the absolute per-unit speed via host.omega (form the deviation as host.omega - dae.omega_net). :param dae: The DAE system object. .. py:class:: PSSKundur Bases: :py:obj:`PSS` Single-input (speed) power system stabilizer: gain, washout, and two lead-lag stages, as in Kundur (Power System Stability and Control, 1994). Vs(s) = K_stab * [ s*Tw / (1 + s*Tw) ] # washout (DC block) * [ (1 + s*T1) / (1 + s*T2) ] # lead-lag 1 * [ (1 + s*T3) / (1 + s*T4) ] # lead-lag 2 * domega # input: SPEED DEVIATION ``host.omega`` is the absolute per-unit rotor speed (= 1.0 at synchronism), NOT the deviation. The PSS input is the deviation from nominal, ``domega = omega - omega_net`` with ``omega_net = 1`` p.u. (``dae.omega_net``), formed explicitly here rather than relying on the washout to subtract the DC offset. The output 'Vs' is summed into the AVR voltage error. Each block contributes one lag-pole state; the two lead-lags (and the washout's high-pass) give the output a direct feedthrough on ``domega``, so 'Vs' is declared as a private ALGEBRAIC variable (read by the AVR via ``Synchronous.pss_signal`` -> ``var_sym('Vs')``). Realization (vw, vl1, vl2 are the three lag-pole states): domega = omega - omega_net ; speed deviation (omega_net = 1 p.u.) u = K_stab * domega vw_dot = (u - vw) / Tw ; washout output w = u - vw vl1_dot = (w - vl1) / T2 ; lead-lag 1 out y1 = vl1(1-T1/T2) + (T1/T2) w vl2_dot = (y1 - vl2) / T4 0 = -Vs + vl2(1-T3/T4) + (T3/T4) y1 At equilibrium ``omega = omega_net`` so ``domega = 0`` and ``vw = vl1 = vl2 = Vs = 0``: the washout blocks DC, hence the PSS does not shift the operating point. .. py:method:: states() -> List[str] Return ordered list of differential-state names. .. py:method:: units() -> List[str] Return units for each state, same length as states(). .. py:method:: algebs() -> List[str] Return ordered list of device-private *algebraic* variable names. A washout + lead-lag PSS returns ['Vs'] here (its output has direct feedthrough on the speed deviation, hence is algebraic) and writes the defining residual ``0 = -Vs + `` into ``dae.g`` in :meth:`fgcall`. .. py:method:: algebs_units() -> Dict[str, str] Units for each private algebraic (mirrors :meth:`units`). .. py:method:: algebs_x0() -> Dict[str, float] Initial guess for each private algebraic (Newton guess in finit). .. py:method:: params() -> Dict[str, float] Return dict of parameter names -> default values. .. py:method:: x0() -> Dict[str, float] Return default initial guess for each state. .. py:method:: descriptions() -> Dict[str, str] Return descriptions for states and params. .. py:method:: fgcall(host, dae: hermess.system.Dae) -> None Write the PSS's differential equations into ``dae.f`` and, if it declares private algebraics (e.g. an algebraic 'Vs'), their defining residuals into ``dae.g``. :param host: The Synchronous machine instance. Access state/algebraic indices via host.vw, host.Vs, etc., parameters via host.K_stab, host.Tw, ..., and the absolute per-unit speed via host.omega (form the deviation as host.omega - dae.omega_net). :param dae: The DAE system object. .. py:class:: PSSSEA Bases: :py:obj:`PSS` Speed-input PSS of the 14-generator South East Australian benchmark (Gibbard & Vowles 2014, Fig. 23 and eqs. (7)-(10)): Vs = sgn·K · [s·Tw/(1+s·Tw)] · Π_{i=1..4} (1+s·Tz_i)/(1+s·Tp_i) · (1 + a·s + b·s²)/((1+s·Tp5)(1+s·Tp6)) · (ω − ω_net) with K = De·Kc (De = 20 pu damping gain on machine MVA base, Kc from Tables 17-20). The four first-order sections cover the real zero/pole chains of eqs. (7)-(9); the quadratic section carries the complex-zero pair of eqs. (8) and (10). Unused first-order slots are made exactly unity by setting Tz_i = Tp_i; an unused quadratic section is exactly unity with a = Tp5+Tp6, b = Tp5·Tp6 (pole-zero cancellation). ``sgn`` is −1 for a hydro machine operating in pumping mode (HPS_1, Case 5). First-order sections are realized as lag state + feedthrough (Tp_i > 0 required); the quadratic section in controllable canonical form with feedthrough c = b/(Tp5·Tp6): ẋ1 = x2 , Tp5·Tp6·ẋ2 = −x1 − (Tp5+Tp6)·x2 + u y = c·u + (1−c)·x1 + (a − c·(Tp5+Tp6))·x2 .. py:method:: states() -> List[str] Return ordered list of differential-state names. .. py:method:: units() -> List[str] Return units for each state, same length as states(). .. py:method:: algebs() -> List[str] Return ordered list of device-private *algebraic* variable names. A washout + lead-lag PSS returns ['Vs'] here (its output has direct feedthrough on the speed deviation, hence is algebraic) and writes the defining residual ``0 = -Vs + `` into ``dae.g`` in :meth:`fgcall`. .. py:method:: algebs_units() -> Dict[str, str] Units for each private algebraic (mirrors :meth:`units`). .. py:method:: algebs_x0() -> Dict[str, float] Initial guess for each private algebraic (Newton guess in finit). .. py:method:: params() -> Dict[str, float] Return dict of parameter names -> default values. .. py:method:: x0() -> Dict[str, float] Return default initial guess for each state. .. py:method:: descriptions() -> Dict[str, str] Return descriptions for states and params. .. py:method:: setpoints() -> Dict[str, float] Return setpoint names -> defaults. A speed-input PSS has none. .. py:method:: fgcall(host, dae: hermess.system.Dae) -> None Write the PSS's differential equations into ``dae.f`` and, if it declares private algebraics (e.g. an algebraic 'Vs'), their defining residuals into ``dae.g``. :param host: The Synchronous machine instance. Access state/algebraic indices via host.vw, host.Vs, etc., parameters via host.K_stab, host.Tw, ..., and the absolute per-unit speed via host.omega (form the deviation as host.omega - dae.omega_net). :param dae: The DAE system object. .. py:data:: PSS_REGISTRY :type: Dict[str, type]