pydynamicestimator.devices.pss ============================== .. py:module:: pydynamicestimator.devices.pss Attributes ---------- .. autoapisummary:: pydynamicestimator.devices.pss.PSS_REGISTRY Classes ------- .. autoapisummary:: pydynamicestimator.devices.pss.PSS pydynamicestimator.devices.pss.PSSKundur 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:`~pydynamicestimator.devices.avr.AVR` and :class:`~pydynamicestimator.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_noise() -> Dict[str, float] Relative process-noise weight for each private algebraic. .. 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:: states_noise() -> Dict[str, float] :abstractmethod: Return noise specification for each state. .. py:method:: states_init_error() -> Dict[str, float] :abstractmethod: Return initial error for each state. .. 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: pydynamicestimator.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 IMPORTANT: ``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``); it is formed explicitly here so the model does not rely 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')``). This is the PSS-side counterpart of the algebraic-``Efd`` lead-lag exciter and the algebraic-``pm`` droop governor. 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_noise() -> Dict[str, float] Relative process-noise weight for each private algebraic. .. 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:: states_noise() -> Dict[str, float] Return noise specification for each state. .. py:method:: states_init_error() -> Dict[str, float] Return initial error for each state. .. 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: pydynamicestimator.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]